@codingame/monaco-vscode-katex-common 28.4.0 → 29.0.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 (154) hide show
  1. package/package.json +2 -2
  2. package/vscode/src/vs/platform/actions/browser/buttonbar.js +2 -2
  3. package/vscode/src/vs/workbench/contrib/chat/browser/accessibility/chatAccessibilityProvider.js +17 -15
  4. package/vscode/src/vs/workbench/contrib/chat/browser/actions/chatContinueInAction.d.ts +2 -2
  5. package/vscode/src/vs/workbench/contrib/chat/browser/actions/chatContinueInAction.js +9 -9
  6. package/vscode/src/vs/workbench/contrib/chat/browser/actions/chatElicitationActions.js +1 -1
  7. package/vscode/src/vs/workbench/contrib/chat/browser/actions/chatExecuteActions.d.ts +3 -1
  8. package/vscode/src/vs/workbench/contrib/chat/browser/actions/chatExecuteActions.js +158 -47
  9. package/vscode/src/vs/workbench/contrib/chat/browser/actions/chatTitleActions.js +22 -17
  10. package/vscode/src/vs/workbench/contrib/chat/browser/agentSessions/agentSessionHoverWidget.js +8 -8
  11. package/vscode/src/vs/workbench/contrib/chat/browser/agentSessions/agentSessionsControl.d.ts +16 -4
  12. package/vscode/src/vs/workbench/contrib/chat/browser/agentSessions/agentSessionsControl.js +121 -14
  13. package/vscode/src/vs/workbench/contrib/chat/browser/agentSessions/agentSessionsFilter.d.ts +8 -1
  14. package/vscode/src/vs/workbench/contrib/chat/browser/agentSessions/agentSessionsFilter.js +15 -8
  15. package/vscode/src/vs/workbench/contrib/chat/browser/agentSessions/agentSessionsOpener.js +1 -1
  16. package/vscode/src/vs/workbench/contrib/chat/browser/agentSessions/agentSessionsViewer.d.ts +29 -13
  17. package/vscode/src/vs/workbench/contrib/chat/browser/agentSessions/agentSessionsViewer.js +349 -109
  18. package/vscode/src/vs/workbench/contrib/chat/browser/agentSessions/media/agentsessionsviewer.css +47 -23
  19. package/vscode/src/vs/workbench/contrib/chat/browser/attachments/chatAttachmentWidgets.d.ts +6 -1
  20. package/vscode/src/vs/workbench/contrib/chat/browser/attachments/chatAttachmentWidgets.js +104 -62
  21. package/vscode/src/vs/workbench/contrib/chat/browser/attachments/chatImplicitContext.js +1 -3
  22. package/vscode/src/vs/workbench/contrib/chat/browser/attachments/implicitContextAttachment.js +13 -11
  23. package/vscode/src/vs/workbench/contrib/chat/browser/chatEditing/chatEditingActions.js +34 -40
  24. package/vscode/src/vs/workbench/contrib/chat/browser/chatEditing/chatEditingEditorActions.js +21 -16
  25. package/vscode/src/vs/workbench/contrib/chat/browser/chatEditing/chatEditingEditorOverlay.js +7 -7
  26. package/vscode/src/vs/workbench/contrib/chat/browser/chatEditing/chatEditingExplanationWidget.js +14 -14
  27. package/vscode/src/vs/workbench/contrib/chat/browser/chatSessions/chatSessionPickerActionItem.d.ts +8 -1
  28. package/vscode/src/vs/workbench/contrib/chat/browser/chatSessions/chatSessionPickerActionItem.js +13 -4
  29. package/vscode/src/vs/workbench/contrib/chat/browser/chatSessions/chatSessions.contribution.d.ts +29 -50
  30. package/vscode/src/vs/workbench/contrib/chat/browser/chatSessions/chatSessions.contribution.js +261 -282
  31. package/vscode/src/vs/workbench/contrib/chat/browser/chatSessions/searchableOptionPickerActionItem.d.ts +2 -1
  32. package/vscode/src/vs/workbench/contrib/chat/browser/chatSessions/searchableOptionPickerActionItem.js +7 -5
  33. package/vscode/src/vs/workbench/contrib/chat/browser/widget/chatAgentHover.js +2 -2
  34. package/vscode/src/vs/workbench/contrib/chat/browser/widget/chatArtifactsWidget.d.ts +31 -0
  35. package/vscode/src/vs/workbench/contrib/chat/browser/widget/chatArtifactsWidget.js +184 -0
  36. package/vscode/src/vs/workbench/contrib/chat/browser/widget/chatContentMarkdownRenderer.js +4 -2
  37. package/vscode/src/vs/workbench/contrib/chat/browser/widget/chatContentParts/chatAgentCommandContentPart.js +1 -1
  38. package/vscode/src/vs/workbench/contrib/chat/browser/widget/chatContentParts/chatAnonymousRateLimitedPart.js +2 -2
  39. package/vscode/src/vs/workbench/contrib/chat/browser/widget/chatContentParts/chatChangesSummaryPart.js +1 -1
  40. package/vscode/src/vs/workbench/contrib/chat/browser/widget/chatContentParts/chatCodeCitationContentPart.js +1 -1
  41. package/vscode/src/vs/workbench/contrib/chat/browser/widget/chatContentParts/chatCommandContentPart.js +1 -1
  42. package/vscode/src/vs/workbench/contrib/chat/browser/widget/chatContentParts/chatConfirmationContentPart.js +2 -2
  43. package/vscode/src/vs/workbench/contrib/chat/browser/widget/chatContentParts/chatConfirmationWidget.js +1 -1
  44. package/vscode/src/vs/workbench/contrib/chat/browser/widget/chatContentParts/chatDisabledClaudeHooksContentPart.js +4 -3
  45. package/vscode/src/vs/workbench/contrib/chat/browser/widget/chatContentParts/chatExtensionsContentPart.js +1 -1
  46. package/vscode/src/vs/workbench/contrib/chat/browser/widget/chatContentParts/chatHookContentPart.js +1 -1
  47. package/vscode/src/vs/workbench/contrib/chat/browser/widget/chatContentParts/chatInlineAnchorWidget.d.ts +3 -2
  48. package/vscode/src/vs/workbench/contrib/chat/browser/widget/chatContentParts/chatInlineAnchorWidget.js +42 -34
  49. package/vscode/src/vs/workbench/contrib/chat/browser/widget/chatContentParts/chatMarkdownContentPart.d.ts +1 -0
  50. package/vscode/src/vs/workbench/contrib/chat/browser/widget/chatContentParts/chatMarkdownContentPart.js +14 -18
  51. package/vscode/src/vs/workbench/contrib/chat/browser/widget/chatContentParts/chatMcpServersInteractionContentPart.js +11 -9
  52. package/vscode/src/vs/workbench/contrib/chat/browser/widget/chatContentParts/chatMultiDiffContentPart.js +4 -4
  53. package/vscode/src/vs/workbench/contrib/chat/browser/widget/chatContentParts/chatProgressContentPart.js +6 -2
  54. package/vscode/src/vs/workbench/contrib/chat/browser/widget/chatContentParts/chatQuestionCarouselPart.d.ts +25 -2
  55. package/vscode/src/vs/workbench/contrib/chat/browser/widget/chatContentParts/chatQuestionCarouselPart.js +332 -114
  56. package/vscode/src/vs/workbench/contrib/chat/browser/widget/chatContentParts/chatQuotaExceededPart.js +4 -4
  57. package/vscode/src/vs/workbench/contrib/chat/browser/widget/chatContentParts/chatReferencesContentPart.d.ts +1 -0
  58. package/vscode/src/vs/workbench/contrib/chat/browser/widget/chatContentParts/chatReferencesContentPart.js +7 -7
  59. package/vscode/src/vs/workbench/contrib/chat/browser/widget/chatContentParts/chatResourceGroupWidget.d.ts +2 -0
  60. package/vscode/src/vs/workbench/contrib/chat/browser/widget/chatContentParts/chatResourceGroupWidget.js +10 -5
  61. package/vscode/src/vs/workbench/contrib/chat/browser/widget/chatContentParts/chatSubagentContentPart.d.ts +1 -1
  62. package/vscode/src/vs/workbench/contrib/chat/browser/widget/chatContentParts/chatSubagentContentPart.js +11 -16
  63. package/vscode/src/vs/workbench/contrib/chat/browser/widget/chatContentParts/chatSuggestNextWidget.d.ts +7 -1
  64. package/vscode/src/vs/workbench/contrib/chat/browser/widget/chatContentParts/chatSuggestNextWidget.js +66 -7
  65. package/vscode/src/vs/workbench/contrib/chat/browser/widget/chatContentParts/chatTextEditContentPart.js +1 -1
  66. package/vscode/src/vs/workbench/contrib/chat/browser/widget/chatContentParts/chatThinkingContentPart.d.ts +28 -3
  67. package/vscode/src/vs/workbench/contrib/chat/browser/widget/chatContentParts/chatThinkingContentPart.js +272 -107
  68. package/vscode/src/vs/workbench/contrib/chat/browser/widget/chatContentParts/chatThinkingExternalResourcesWidget.d.ts +18 -0
  69. package/vscode/src/vs/workbench/contrib/chat/browser/widget/chatContentParts/chatThinkingExternalResourcesWidget.js +70 -0
  70. package/vscode/src/vs/workbench/contrib/chat/browser/widget/chatContentParts/chatTipContentPart.js +9 -9
  71. package/vscode/src/vs/workbench/contrib/chat/browser/widget/chatContentParts/chatTodoListWidget.js +17 -17
  72. package/vscode/src/vs/workbench/contrib/chat/browser/widget/chatContentParts/chatToolInputOutputContentPart.d.ts +1 -1
  73. package/vscode/src/vs/workbench/contrib/chat/browser/widget/chatContentParts/chatToolInputOutputContentPart.js +6 -3
  74. package/vscode/src/vs/workbench/contrib/chat/browser/widget/chatContentParts/chatTreeContentPart.js +1 -1
  75. package/vscode/src/vs/workbench/contrib/chat/browser/widget/chatContentParts/chatWorkspaceEditContentPart.js +3 -3
  76. package/vscode/src/vs/workbench/contrib/chat/browser/widget/chatContentParts/codeBlockPart.js +14 -14
  77. package/vscode/src/vs/workbench/contrib/chat/browser/widget/chatContentParts/media/chatConfirmationWidget.css +151 -0
  78. package/vscode/src/vs/workbench/contrib/chat/browser/widget/chatContentParts/media/chatInlineAnchorWidget.css +6 -6
  79. package/vscode/src/vs/workbench/contrib/chat/browser/widget/chatContentParts/media/chatQuestionCarousel.css +96 -10
  80. package/vscode/src/vs/workbench/contrib/chat/browser/widget/chatContentParts/media/chatTerminalToolProgressPart.css +6 -1
  81. package/vscode/src/vs/workbench/contrib/chat/browser/widget/chatContentParts/media/chatThinkingContent.css +86 -10
  82. package/vscode/src/vs/workbench/contrib/chat/browser/widget/chatContentParts/toolInvocationParts/abstractToolConfirmationSubPart.d.ts +7 -0
  83. package/vscode/src/vs/workbench/contrib/chat/browser/widget/chatContentParts/toolInvocationParts/abstractToolConfirmationSubPart.js +5 -2
  84. package/vscode/src/vs/workbench/contrib/chat/browser/widget/chatContentParts/toolInvocationParts/chatExtensionsInstallToolSubPart.js +4 -4
  85. package/vscode/src/vs/workbench/contrib/chat/browser/widget/chatContentParts/toolInvocationParts/chatInputOutputMarkdownProgressPart.d.ts +1 -1
  86. package/vscode/src/vs/workbench/contrib/chat/browser/widget/chatContentParts/toolInvocationParts/chatInputOutputMarkdownProgressPart.js +8 -6
  87. package/vscode/src/vs/workbench/contrib/chat/browser/widget/chatContentParts/toolInvocationParts/chatMcpAppModel.js +1 -1
  88. package/vscode/src/vs/workbench/contrib/chat/browser/widget/chatContentParts/toolInvocationParts/chatMcpAppSubPart.js +3 -3
  89. package/vscode/src/vs/workbench/contrib/chat/browser/widget/chatContentParts/toolInvocationParts/chatModifiedFilesConfirmationSubPart.d.ts +28 -0
  90. package/vscode/src/vs/workbench/contrib/chat/browser/widget/chatContentParts/toolInvocationParts/chatModifiedFilesConfirmationSubPart.js +273 -0
  91. package/vscode/src/vs/workbench/contrib/chat/browser/widget/chatContentParts/toolInvocationParts/chatSimpleToolProgressPart.js +3 -2
  92. package/vscode/src/vs/workbench/contrib/chat/browser/widget/chatContentParts/toolInvocationParts/chatTerminalToolConfirmationSubPart.js +28 -16
  93. package/vscode/src/vs/workbench/contrib/chat/browser/widget/chatContentParts/toolInvocationParts/chatTerminalToolProgressPart.d.ts +22 -1
  94. package/vscode/src/vs/workbench/contrib/chat/browser/widget/chatContentParts/toolInvocationParts/chatTerminalToolProgressPart.js +81 -32
  95. package/vscode/src/vs/workbench/contrib/chat/browser/widget/chatContentParts/toolInvocationParts/chatToolConfirmationSubPart.d.ts +1 -0
  96. package/vscode/src/vs/workbench/contrib/chat/browser/widget/chatContentParts/toolInvocationParts/chatToolConfirmationSubPart.js +20 -7
  97. package/vscode/src/vs/workbench/contrib/chat/browser/widget/chatContentParts/toolInvocationParts/chatToolInvocationPart.js +11 -1
  98. package/vscode/src/vs/workbench/contrib/chat/browser/widget/chatContentParts/toolInvocationParts/chatToolOutputPart.js +2 -2
  99. package/vscode/src/vs/workbench/contrib/chat/browser/widget/chatContentParts/toolInvocationParts/chatToolPartUtilities.d.ts +6 -0
  100. package/vscode/src/vs/workbench/contrib/chat/browser/widget/chatContentParts/toolInvocationParts/chatToolPartUtilities.js +21 -7
  101. package/vscode/src/vs/workbench/contrib/chat/browser/widget/chatContentParts/toolInvocationParts/chatToolPostExecuteConfirmationPart.js +5 -5
  102. package/vscode/src/vs/workbench/contrib/chat/browser/widget/chatContentParts/toolInvocationParts/chatToolProgressPart.js +2 -12
  103. package/vscode/src/vs/workbench/contrib/chat/browser/widget/chatDragAndDrop.js +12 -12
  104. package/vscode/src/vs/workbench/contrib/chat/browser/widget/chatListRenderer.d.ts +0 -6
  105. package/vscode/src/vs/workbench/contrib/chat/browser/widget/chatListRenderer.js +112 -163
  106. package/vscode/src/vs/workbench/contrib/chat/browser/widget/chatListWidget.js +11 -1
  107. package/vscode/src/vs/workbench/contrib/chat/browser/widget/chatWidget.d.ts +9 -1
  108. package/vscode/src/vs/workbench/contrib/chat/browser/widget/chatWidget.js +137 -52
  109. package/vscode/src/vs/workbench/contrib/chat/browser/widget/input/chatFollowups.js +1 -1
  110. package/vscode/src/vs/workbench/contrib/chat/browser/widget/input/chatInputPart.d.ts +12 -0
  111. package/vscode/src/vs/workbench/contrib/chat/browser/widget/input/chatInputPart.js +108 -38
  112. package/vscode/src/vs/workbench/contrib/chat/browser/widget/input/chatModelPicker.d.ts +9 -3
  113. package/vscode/src/vs/workbench/contrib/chat/browser/widget/input/chatModelPicker.js +385 -247
  114. package/vscode/src/vs/workbench/contrib/chat/browser/widget/input/delegationSessionPickerActionItem.d.ts +5 -1
  115. package/vscode/src/vs/workbench/contrib/chat/browser/widget/input/delegationSessionPickerActionItem.js +23 -7
  116. package/vscode/src/vs/workbench/contrib/chat/browser/widget/input/modePickerActionItem.js +6 -6
  117. package/vscode/src/vs/workbench/contrib/chat/browser/widget/input/modelPickerActionItem.d.ts +4 -1
  118. package/vscode/src/vs/workbench/contrib/chat/browser/widget/input/modelPickerActionItem2.js +4 -2
  119. package/vscode/src/vs/workbench/contrib/chat/browser/widget/input/permissionPickerActionItem.js +23 -23
  120. package/vscode/src/vs/workbench/contrib/chat/browser/widget/input/sessionTargetPickerActionItem.js +3 -3
  121. package/vscode/src/vs/workbench/contrib/chat/browser/widget/input/workspacePickerActionItem.js +3 -3
  122. package/vscode/src/vs/workbench/contrib/chat/browser/widget/media/chat.css +124 -17
  123. package/vscode/src/vs/workbench/contrib/chat/browser/widgetHosts/viewPane/chatContextUsageDetails.d.ts +4 -0
  124. package/vscode/src/vs/workbench/contrib/chat/browser/widgetHosts/viewPane/chatContextUsageDetails.js +24 -7
  125. package/vscode/src/vs/workbench/contrib/chat/browser/widgetHosts/viewPane/chatContextUsageWidget.js +30 -11
  126. package/vscode/src/vs/workbench/contrib/chat/browser/widgetHosts/viewPane/media/chatContextUsageDetails.css +84 -0
  127. package/vscode/src/vs/workbench/contrib/chat/common/chatImageExtraction.d.ts +31 -0
  128. package/vscode/src/vs/workbench/contrib/chat/common/chatImageExtraction.js +170 -0
  129. package/vscode/src/vs/workbench/contrib/chat/common/promptSyntax/internalCustomizations/internalPromptFileSystem.d.ts +47 -0
  130. package/vscode/src/vs/workbench/contrib/chat/common/promptSyntax/internalCustomizations/internalPromptFileSystem.js +95 -0
  131. package/vscode/src/vs/workbench/contrib/chat/common/widget/annotations.js +4 -1
  132. package/vscode/src/vs/workbench/contrib/chat/common/widget/chatColors.js +15 -15
  133. package/vscode/src/vs/workbench/contrib/inlineChat/browser/inlineChatAffordance.d.ts +1 -1
  134. package/vscode/src/vs/workbench/contrib/inlineChat/browser/inlineChatAffordance.js +4 -3
  135. package/vscode/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.d.ts +2 -0
  136. package/vscode/src/vs/workbench/contrib/inlineChat/browser/inlineChatController.js +38 -6
  137. package/vscode/src/vs/workbench/contrib/inlineChat/browser/inlineChatEditorAffordance.d.ts +1 -0
  138. package/vscode/src/vs/workbench/contrib/inlineChat/browser/inlineChatEditorAffordance.js +31 -0
  139. package/vscode/src/vs/workbench/contrib/inlineChat/browser/inlineChatOverlayWidget.d.ts +12 -3
  140. package/vscode/src/vs/workbench/contrib/inlineChat/browser/inlineChatOverlayWidget.js +130 -23
  141. package/vscode/src/vs/workbench/contrib/inlineChat/browser/inlineChatSessionService.d.ts +23 -0
  142. package/vscode/src/vs/workbench/contrib/inlineChat/browser/inlineChatSessionService.js +41 -0
  143. package/vscode/src/vs/workbench/contrib/inlineChat/browser/inlineChatWidget.js +5 -5
  144. package/vscode/src/vs/workbench/contrib/inlineChat/browser/inlineChatZoneWidget.js +1 -1
  145. package/vscode/src/vs/workbench/contrib/inlineChat/browser/media/inlineChatOverlayWidget.css +55 -3
  146. package/vscode/src/vs/workbench/contrib/inlineChat/common/inlineChat.d.ts +4 -1
  147. package/vscode/src/vs/workbench/contrib/inlineChat/common/inlineChat.js +50 -39
  148. package/vscode/src/vs/workbench/contrib/interactive/browser/replInputHintContentWidget.js +3 -3
  149. package/vscode/src/vs/workbench/contrib/notebook/browser/contrib/cellStatusBar/executionStatusBarItemController.js +7 -7
  150. package/vscode/src/vs/workbench/contrib/notebook/browser/contrib/find/notebookFindWidget.js +2 -2
  151. package/vscode/src/vs/workbench/contrib/replNotebook/browser/replEditor.js +1 -1
  152. package/vscode/src/vs/workbench/contrib/replNotebook/browser/replEditorInput.js +1 -1
  153. package/vscode/src/vs/workbench/contrib/chat/browser/widget/chatQuestionCarouselAutoReply.d.ts +0 -35
  154. package/vscode/src/vs/workbench/contrib/chat/browser/widget/chatQuestionCarouselAutoReply.js +0 -440
@@ -9,6 +9,7 @@ import { isMarkdownString, MarkdownString } from '@codingame/monaco-vscode-api/v
9
9
  import { KeyCode } from '@codingame/monaco-vscode-api/vscode/vs/base/common/keyCodes';
10
10
  import { Disposable, DisposableStore, MutableDisposable } from '@codingame/monaco-vscode-api/vscode/vs/base/common/lifecycle';
11
11
  import { isMacintosh } from '@codingame/monaco-vscode-api/vscode/vs/base/common/platform';
12
+ import { generateUuid } from '@codingame/monaco-vscode-api/vscode/vs/base/common/uuid';
12
13
  import { hasKey } from '@codingame/monaco-vscode-api/vscode/vs/base/common/types';
13
14
  import { localize } from '@codingame/monaco-vscode-api/vscode/vs/nls';
14
15
  import { IAccessibilityService } from '@codingame/monaco-vscode-api/vscode/vs/platform/accessibility/common/accessibility.service';
@@ -55,6 +56,7 @@ let ChatQuestionCarouselPart = class ChatQuestionCarouselPart extends Disposable
55
56
  this.onDidChangeHeight = this._onDidChangeHeight.event;
56
57
  this._currentIndex = 0;
57
58
  this._answers = ( new Map());
59
+ this._isCollapsed = false;
58
60
  this._isSkipped = false;
59
61
  this._textInputBoxes = ( new Map());
60
62
  this._singleSelectItems = ( new Map());
@@ -64,6 +66,7 @@ let ChatQuestionCarouselPart = class ChatQuestionCarouselPart extends Disposable
64
66
  this._questionRenderStore = this._register(( new MutableDisposable()));
65
67
  this._interactiveUIStore = this._register(( new MutableDisposable()));
66
68
  this.domNode = $(".chat-question-carousel-container");
69
+ this.domNode.id = generateUuid();
67
70
  this._inChatQuestionCarouselContextKey = ChatContextKeys.inChatQuestionCarousel.bindTo(this._contextKeyService);
68
71
  const focusTracker = this._register(trackFocus(this.domNode));
69
72
  this._register(
@@ -77,12 +80,15 @@ let ChatQuestionCarouselPart = class ChatQuestionCarouselPart extends Disposable
77
80
  });
78
81
  this.domNode.tabIndex = 0;
79
82
  this.domNode.setAttribute("role", "region");
80
- this.domNode.setAttribute("aria-roledescription", ( localize(6542, "chat question")));
83
+ this.domNode.setAttribute("aria-roledescription", ( localize(6716, "chat question")));
81
84
  this._updateAriaLabel();
82
85
  if (carousel instanceof ChatQuestionCarouselData) {
83
86
  if (typeof carousel.draftCurrentIndex === "number") {
84
87
  this._currentIndex = Math.max(0, Math.min(carousel.draftCurrentIndex, carousel.questions.length - 1));
85
88
  }
89
+ if (typeof carousel.draftCollapsed === "boolean") {
90
+ this._isCollapsed = carousel.draftCollapsed;
91
+ }
86
92
  if (carousel.draftAnswers) {
87
93
  for (const [key, value] of Object.entries(carousel.draftAnswers)) {
88
94
  this._answers.set(key, value);
@@ -105,9 +111,19 @@ let ChatQuestionCarouselPart = class ChatQuestionCarouselPart extends Disposable
105
111
  this._interactiveUIStore.value = interactiveStore;
106
112
  this._questionContainer = $(".chat-question-carousel-content");
107
113
  this.domNode.append(this._questionContainer);
114
+ this._headerActionsContainer = $(".chat-question-header-actions");
115
+ const collapseToggleTitle = ( localize(6717, "Collapse Questions"));
116
+ const collapseButton = interactiveStore.add(( new Button(this._headerActionsContainer, {
117
+ ...defaultButtonStyles,
118
+ secondary: true,
119
+ supportIcons: true
120
+ })));
121
+ collapseButton.element.classList.add("chat-question-collapse-toggle");
122
+ collapseButton.element.setAttribute("aria-label", collapseToggleTitle);
123
+ this._collapseButton = collapseButton;
108
124
  if (carousel.allowSkip) {
109
125
  this._closeButtonContainer = $(".chat-question-close-container");
110
- const skipAllTitle = ( localize(6543, "Skip all questions"));
126
+ const skipAllTitle = ( localize(6718, "Skip all questions"));
111
127
  const skipAllButton = interactiveStore.add(( new Button(this._closeButtonContainer, {
112
128
  ...defaultButtonStyles,
113
129
  secondary: true,
@@ -121,6 +137,7 @@ let ChatQuestionCarouselPart = class ChatQuestionCarouselPart extends Disposable
121
137
  }));
122
138
  this._skipAllButton = skipAllButton;
123
139
  }
140
+ interactiveStore.add(collapseButton.onDidClick(() => this.toggleCollapsed()));
124
141
  if (this._skipAllButton) {
125
142
  interactiveStore.add(this._skipAllButton.onDidClick(() => this.ignore()));
126
143
  }
@@ -157,6 +174,17 @@ let ChatQuestionCarouselPart = class ChatQuestionCarouselPart extends Disposable
157
174
  } else {
158
175
  this._answers.delete(currentQuestion.id);
159
176
  }
177
+ if (currentQuestion?.validation && typeof answer === "string" && answer !== "") {
178
+ const error = this.getValidationError(answer, currentQuestion.validation);
179
+ if (error) {
180
+ this.showValidationError(error);
181
+ } else {
182
+ this.clearValidationError();
183
+ }
184
+ } else {
185
+ this.clearValidationError();
186
+ }
187
+ this.updateFooterState();
160
188
  this.persistDraftState();
161
189
  }
162
190
  persistDraftState() {
@@ -165,6 +193,26 @@ let ChatQuestionCarouselPart = class ChatQuestionCarouselPart extends Disposable
165
193
  }
166
194
  this.carousel.draftAnswers = Object.fromEntries(this._answers.entries());
167
195
  this.carousel.draftCurrentIndex = this._currentIndex;
196
+ this.carousel.draftCollapsed = this._isCollapsed;
197
+ }
198
+ toggleCollapsed() {
199
+ this._isCollapsed = !this._isCollapsed;
200
+ this.persistDraftState();
201
+ this.updateCollapsedPresentation();
202
+ this._onDidChangeHeight.fire();
203
+ }
204
+ updateCollapsedPresentation() {
205
+ this.domNode.classList.toggle("chat-question-carousel-collapsed", this._isCollapsed);
206
+ if (this._collapseButton) {
207
+ const collapsed = this._isCollapsed;
208
+ const buttonTitle = collapsed ? ( localize(6719, "Expand Questions")) : ( localize(6717, "Collapse Questions"));
209
+ const contentId = this.domNode.id;
210
+ this._collapseButton.label = collapsed ? `$(${Codicon.chevronUp.id})` : `$(${Codicon.chevronDown.id})`;
211
+ this._collapseButton.element.setAttribute("aria-label", buttonTitle);
212
+ this._collapseButton.element.setAttribute("aria-expanded", String(!collapsed));
213
+ this._collapseButton.element.setAttribute("aria-controls", contentId);
214
+ this._collapseButton.setTitle(buttonTitle);
215
+ }
168
216
  }
169
217
  navigate(delta) {
170
218
  const newIndex = this._currentIndex + delta;
@@ -178,17 +226,29 @@ let ChatQuestionCarouselPart = class ChatQuestionCarouselPart extends Disposable
178
226
  }
179
227
  handleNextOrSubmit() {
180
228
  this.saveCurrentAnswer();
229
+ if (!this.validateCurrentQuestion()) {
230
+ return;
231
+ }
181
232
  if (this._currentIndex < this.carousel.questions.length - 1) {
182
233
  this._currentIndex++;
183
234
  this.persistDraftState();
184
235
  this.renderCurrentQuestion(true);
185
236
  } else {
237
+ if (!this.validateRequiredFields()) {
238
+ return;
239
+ }
186
240
  this._options.onSubmit(this._answers);
187
241
  this.hideAndShowSummary();
188
242
  }
189
243
  }
190
244
  submit() {
191
245
  this.saveCurrentAnswer();
246
+ if (!this.validateCurrentQuestion()) {
247
+ return;
248
+ }
249
+ if (!this.validateRequiredFields()) {
250
+ return;
251
+ }
192
252
  this._options.onSubmit(this._answers);
193
253
  this.hideAndShowSummary();
194
254
  }
@@ -200,7 +260,7 @@ let ChatQuestionCarouselPart = class ChatQuestionCarouselPart extends Disposable
200
260
  const messageContent = this.getQuestionText(questionText);
201
261
  const questionCount = this.carousel.questions.length;
202
262
  const alertMessage = questionCount === 1 ? messageContent : ( localize(
203
- 6544,
263
+ 6720,
204
264
  "Question {0} of {1}: {2}",
205
265
  this._currentIndex + 1,
206
266
  questionCount,
@@ -230,7 +290,9 @@ let ChatQuestionCarouselPart = class ChatQuestionCarouselPart extends Disposable
230
290
  this._submitButton = undefined;
231
291
  this._skipAllButton = undefined;
232
292
  this._questionContainer = undefined;
293
+ this._headerActionsContainer = undefined;
233
294
  this._closeButtonContainer = undefined;
295
+ this._collapseButton = undefined;
234
296
  this._footerRow = undefined;
235
297
  this._stepIndicator = undefined;
236
298
  this._submitHint = undefined;
@@ -310,7 +372,7 @@ let ChatQuestionCarouselPart = class ChatQuestionCarouselPart extends Disposable
310
372
  getDefaultAnswerForQuestion(question) {
311
373
  switch (question.type) {
312
374
  case "text":
313
- return question.defaultValue;
375
+ return typeof question.defaultValue === "string" ? question.defaultValue : undefined;
314
376
  case "singleSelect":
315
377
  {
316
378
  const defaultOptionId = typeof question.defaultValue === "string" ? question.defaultValue : undefined;
@@ -331,7 +393,9 @@ let ChatQuestionCarouselPart = class ChatQuestionCarouselPart extends Disposable
331
393
  } : undefined;
332
394
  }
333
395
  default:
334
- return question.defaultValue;
396
+ return typeof question.defaultValue === "string" ? question.defaultValue : Array.isArray(question.defaultValue) ? {
397
+ selectedValues: question.defaultValue
398
+ } : undefined;
335
399
  }
336
400
  }
337
401
  _shouldAutoFocus() {
@@ -343,17 +407,17 @@ let ChatQuestionCarouselPart = class ChatQuestionCarouselPart extends Disposable
343
407
  _updateAriaLabel() {
344
408
  const question = this.carousel.questions[this._currentIndex];
345
409
  if (!question) {
346
- this.domNode.setAttribute("aria-label", ( localize(6545, "Chat question")));
410
+ this.domNode.setAttribute("aria-label", ( localize(6721, "Chat question")));
347
411
  return;
348
412
  }
349
413
  const questionText = question.message ?? question.title;
350
414
  const messageContent = this.getQuestionText(questionText);
351
415
  const questionCount = this.carousel.questions.length;
352
416
  if (questionCount === 1) {
353
- this.domNode.setAttribute("aria-label", ( localize(6546, "Chat question: {0}", messageContent)));
417
+ this.domNode.setAttribute("aria-label", ( localize(6722, "Chat question: {0}", messageContent)));
354
418
  } else {
355
419
  this.domNode.setAttribute("aria-label", ( localize(
356
- 6547,
420
+ 6723,
357
421
  "Chat question {0} of {1}: {2}",
358
422
  this._currentIndex + 1,
359
423
  questionCount,
@@ -400,21 +464,40 @@ let ChatQuestionCarouselPart = class ChatQuestionCarouselPart extends Disposable
400
464
  }
401
465
  const headerRow = $(".chat-question-header-row");
402
466
  const titleRow = $(".chat-question-title-row");
467
+ if (this.carousel.message && this._currentIndex === 0) {
468
+ const messageMd = isMarkdownString(this.carousel.message) ? MarkdownString.lift(this.carousel.message) : ( new MarkdownString(this.carousel.message));
469
+ const carouselMessage = $(".chat-question-carousel-message");
470
+ const renderedMessage = questionRenderStore.add(this._markdownRendererService.render(messageMd));
471
+ carouselMessage.appendChild(renderedMessage.element);
472
+ headerRow.appendChild(carouselMessage);
473
+ }
403
474
  const questionText = question.message ?? question.title;
404
475
  if (questionText) {
405
476
  const title = $(".chat-question-title");
406
477
  const messageContent = this.getQuestionText(questionText);
407
478
  title.setAttribute("aria-label", messageContent);
408
- const messageMd = isMarkdownString(questionText) ? MarkdownString.lift(questionText) : ( new MarkdownString(questionText));
409
- const renderedTitle = questionRenderStore.add(this._markdownRendererService.render(messageMd));
479
+ const titleText = question.required ? ( new MarkdownString(`${isMarkdownString(questionText) ? questionText.value : questionText} *`)) : (isMarkdownString(questionText) ? MarkdownString.lift(questionText) : ( new MarkdownString(questionText)));
480
+ const renderedTitle = questionRenderStore.add(this._markdownRendererService.render(titleText));
410
481
  title.appendChild(renderedTitle.element);
411
482
  titleRow.appendChild(title);
412
483
  }
413
484
  headerRow.appendChild(titleRow);
414
- if (this._closeButtonContainer) {
415
- titleRow.appendChild(this._closeButtonContainer);
485
+ if (this._headerActionsContainer) {
486
+ clearNode(this._headerActionsContainer);
487
+ if (this._closeButtonContainer) {
488
+ this._headerActionsContainer.appendChild(this._closeButtonContainer);
489
+ }
490
+ if (this._collapseButton) {
491
+ this._headerActionsContainer.appendChild(this._collapseButton.element);
492
+ }
493
+ titleRow.appendChild(this._headerActionsContainer);
416
494
  }
417
495
  this._questionContainer.appendChild(headerRow);
496
+ if (question.description) {
497
+ const descriptionEl = $(".chat-question-description");
498
+ descriptionEl.textContent = question.description;
499
+ this._questionContainer.appendChild(descriptionEl);
500
+ }
418
501
  const inputContainer = $(".chat-question-input-container");
419
502
  this.renderInput(inputContainer, question);
420
503
  const inputScrollable = questionRenderStore.add(( new DomScrollableElement(inputContainer, {
@@ -426,6 +509,9 @@ let ChatQuestionCarouselPart = class ChatQuestionCarouselPart extends Disposable
426
509
  const inputScrollableNode = inputScrollable.getDomNode();
427
510
  inputScrollableNode.classList.add("chat-question-input-scrollable");
428
511
  this._questionContainer.appendChild(inputScrollableNode);
512
+ this._validationMessageElement = $(".chat-question-validation-message");
513
+ this._validationMessageElement.style.display = "none";
514
+ this._questionContainer.appendChild(this._validationMessageElement);
429
515
  const isSingleQuestion = this.carousel.questions.length === 1;
430
516
  if (!isSingleQuestion) {
431
517
  this.renderFooter();
@@ -447,6 +533,11 @@ let ChatQuestionCarouselPart = class ChatQuestionCarouselPart extends Disposable
447
533
  const inputResizeObserver = questionRenderStore.add(new DisposableResizeObserver(() => scheduleLayoutInputScrollable()));
448
534
  questionRenderStore.add(inputResizeObserver.observe(inputScrollableNode));
449
535
  questionRenderStore.add(inputResizeObserver.observe(inputContainer));
536
+ questionRenderStore.add(addDisposableListener(
537
+ getWindow(this.domNode),
538
+ EventType.RESIZE,
539
+ () => scheduleLayoutInputScrollable()
540
+ ));
450
541
  scheduleLayoutInputScrollable();
451
542
  questionRenderStore.add(
452
543
  runAtThisOrScheduleAtNextAnimationFrame(getWindow(this.domNode), () => {
@@ -460,6 +551,7 @@ let ChatQuestionCarouselPart = class ChatQuestionCarouselPart extends Disposable
460
551
  })
461
552
  );
462
553
  this._updateAriaLabel();
554
+ this.updateCollapsedPresentation();
463
555
  if (focusContainerForScreenReader && this._accessibilityService.isScreenReaderOptimized()) {
464
556
  this._focusContainerAndAnnounce();
465
557
  }
@@ -474,9 +566,9 @@ let ChatQuestionCarouselPart = class ChatQuestionCarouselPart extends Disposable
474
566
  this._footerRow = $(".chat-question-footer-row");
475
567
  const leftControls = $(".chat-question-footer-left.chat-question-carousel-nav");
476
568
  leftControls.setAttribute("role", "navigation");
477
- leftControls.setAttribute("aria-label", ( localize(6548, "Question navigation")));
569
+ leftControls.setAttribute("aria-label", ( localize(6724, "Question navigation")));
478
570
  const arrowsContainer = $(".chat-question-nav-arrows");
479
- const previousLabel = this.getLabelWithKeybinding(( localize(6549, "Previous")), PREVIOUS_QUESTION_ACTION_ID);
571
+ const previousLabel = this.getLabelWithKeybinding(( localize(6725, "Previous")), PREVIOUS_QUESTION_ACTION_ID);
480
572
  const prevButton = interactiveStore.add(( new Button(arrowsContainer, {
481
573
  ...defaultButtonStyles,
482
574
  secondary: true,
@@ -490,7 +582,7 @@ let ChatQuestionCarouselPart = class ChatQuestionCarouselPart extends Disposable
490
582
  }));
491
583
  interactiveStore.add(prevButton.onDidClick(() => this.navigate(-1)));
492
584
  this._prevButton = prevButton;
493
- const nextLabel = this.getLabelWithKeybinding(( localize(6550, "Next")), NEXT_QUESTION_ACTION_ID);
585
+ const nextLabel = this.getLabelWithKeybinding(( localize(6726, "Next")), NEXT_QUESTION_ACTION_ID);
494
586
  const nextButton = interactiveStore.add(( new Button(arrowsContainer, {
495
587
  ...defaultButtonStyles,
496
588
  secondary: true,
@@ -510,14 +602,14 @@ let ChatQuestionCarouselPart = class ChatQuestionCarouselPart extends Disposable
510
602
  this._footerRow.appendChild(leftControls);
511
603
  const rightControls = $(".chat-question-footer-right");
512
604
  const hint = $("span.chat-question-submit-hint");
513
- hint.textContent = isMacintosh ? ( localize(6551, "⌘⏎ to submit")) : ( localize(6552, "Ctrl+Enter to submit"));
605
+ hint.textContent = isMacintosh ? ( localize(6727, "⌘⏎ to submit")) : ( localize(6728, "Ctrl+Enter to submit"));
514
606
  rightControls.appendChild(hint);
515
607
  this._submitHint = hint;
516
608
  const submitButton = interactiveStore.add(( new Button(rightControls, {
517
609
  ...defaultButtonStyles
518
610
  })));
519
611
  submitButton.element.classList.add("chat-question-submit-button");
520
- submitButton.label = ( localize(6553, "Submit"));
612
+ submitButton.label = ( localize(6729, "Submit"));
521
613
  interactiveStore.add(submitButton.onDidClick(() => this.submit()));
522
614
  this._submitButton = submitButton;
523
615
  this._footerRow.appendChild(rightControls);
@@ -530,10 +622,15 @@ let ChatQuestionCarouselPart = class ChatQuestionCarouselPart extends Disposable
530
622
  this._prevButton.enabled = this._currentIndex > 0;
531
623
  }
532
624
  if (this._nextButton) {
533
- this._nextButton.enabled = this._currentIndex < this.carousel.questions.length - 1;
625
+ const canAdvance = this._currentIndex < this.carousel.questions.length - 1;
626
+ const question = this.carousel.questions[this._currentIndex];
627
+ const answer = this._answers.get(question?.id);
628
+ const hasAnswer = answer !== undefined && answer !== "";
629
+ const hasValidationError = !!this._currentValidationError;
630
+ this._nextButton.enabled = canAdvance && (!question?.required || hasAnswer) && !hasValidationError;
534
631
  }
535
632
  if (this._stepIndicator) {
536
- this._stepIndicator.textContent = ( localize(6554, "{0}/{1}", this._currentIndex + 1, this.carousel.questions.length));
633
+ this._stepIndicator.textContent = ( localize(6730, "{0}/{1}", this._currentIndex + 1, this.carousel.questions.length));
537
634
  }
538
635
  if (this._submitButton) {
539
636
  const isLastQuestion = this._currentIndex === this.carousel.questions.length - 1;
@@ -552,18 +649,18 @@ let ChatQuestionCarouselPart = class ChatQuestionCarouselPart extends Disposable
552
649
  this._footerRow = $(".chat-question-footer-row");
553
650
  const leftControls = $(".chat-question-footer-left.chat-question-carousel-nav");
554
651
  leftControls.setAttribute("role", "navigation");
555
- leftControls.setAttribute("aria-label", ( localize(6548, "Question navigation")));
652
+ leftControls.setAttribute("aria-label", ( localize(6724, "Question navigation")));
556
653
  this._footerRow.appendChild(leftControls);
557
654
  const rightControls = $(".chat-question-footer-right");
558
655
  const hint = $("span.chat-question-submit-hint");
559
- hint.textContent = isMacintosh ? ( localize(6551, "⌘⏎ to submit")) : ( localize(6552, "Ctrl+Enter to submit"));
656
+ hint.textContent = isMacintosh ? ( localize(6727, "⌘⏎ to submit")) : ( localize(6728, "Ctrl+Enter to submit"));
560
657
  rightControls.appendChild(hint);
561
658
  this._submitHint = hint;
562
659
  const submitButton = interactiveStore.add(( new Button(rightControls, {
563
660
  ...defaultButtonStyles
564
661
  })));
565
662
  submitButton.element.classList.add("chat-question-submit-button");
566
- submitButton.label = ( localize(6553, "Submit"));
663
+ submitButton.label = ( localize(6729, "Submit"));
567
664
  interactiveStore.add(submitButton.onDidClick(() => this.submit()));
568
665
  this._submitButton = submitButton;
569
666
  this._footerRow.appendChild(rightControls);
@@ -572,7 +669,7 @@ let ChatQuestionCarouselPart = class ChatQuestionCarouselPart extends Disposable
572
669
  }
573
670
  getLabelWithKeybinding(label, actionId) {
574
671
  const keybindingLabel = this._keybindingService.lookupKeybinding(actionId, this._contextKeyService)?.getLabel();
575
- return keybindingLabel ? ( localize(6555, "{0} ({1})", label, keybindingLabel)) : label;
672
+ return keybindingLabel ? ( localize(6731, "{0} ({1})", label, keybindingLabel)) : label;
576
673
  }
577
674
  renderInput(container, question) {
578
675
  switch (question.type) {
@@ -601,10 +698,27 @@ let ChatQuestionCarouselPart = class ChatQuestionCarouselPart extends Disposable
601
698
  }
602
699
  renderTextInput(container, question) {
603
700
  const inputBox = this._inputBoxes.add(( new InputBox(container, undefined, {
604
- placeholder: ( localize(6556, "Enter your answer")),
605
- inputBoxStyles: defaultInputBoxStyles
701
+ placeholder: ( localize(6732, "Enter your answer")),
702
+ inputBoxStyles: defaultInputBoxStyles,
703
+ validationOptions: question.validation ? {
704
+ validation: value => {
705
+ if (!value && !question.required) {
706
+ return null;
707
+ }
708
+ const error = this.getValidationError(value, question.validation);
709
+ if (error) {
710
+ return {
711
+ type: 2 ,
712
+ content: error
713
+ };
714
+ }
715
+ return null;
716
+ }
717
+ } : undefined
606
718
  })));
607
- this._inputBoxes.add(inputBox.onDidChange(() => this.saveCurrentAnswer()));
719
+ this._inputBoxes.add(inputBox.onDidChange(() => {
720
+ this.saveCurrentAnswer();
721
+ }));
608
722
  const previousAnswer = this._answers.get(question.id);
609
723
  if (previousAnswer !== undefined) {
610
724
  inputBox.value = String(previousAnswer);
@@ -626,12 +740,11 @@ let ChatQuestionCarouselPart = class ChatQuestionCarouselPart extends Disposable
626
740
  selectContainer.tabIndex = 0;
627
741
  container.appendChild(selectContainer);
628
742
  const previousAnswer = this._answers.get(question.id);
629
- const previousFreeform = typeof previousAnswer === "object" && previousAnswer !== null && hasKey(previousAnswer, {
630
- freeformValue: true
631
- }) ? previousAnswer.freeformValue : undefined;
632
- const previousSelectedValue = typeof previousAnswer === "object" && previousAnswer !== null && hasKey(previousAnswer, {
743
+ const prevSingle = typeof previousAnswer === "object" && previousAnswer !== null && hasKey(previousAnswer, {
633
744
  selectedValue: true
634
- }) ? previousAnswer.selectedValue : previousAnswer;
745
+ }) ? previousAnswer : undefined;
746
+ const previousFreeform = prevSingle?.freeformValue;
747
+ const previousSelectedValue = prevSingle?.selectedValue;
635
748
  const defaultOptionId = typeof question.defaultValue === "string" ? question.defaultValue : undefined;
636
749
  let selectedIndex = -1;
637
750
  options.forEach((option, index) => {
@@ -666,7 +779,7 @@ let ChatQuestionCarouselPart = class ChatQuestionCarouselPart extends Disposable
666
779
  const listItem = $(".chat-question-list-item");
667
780
  listItem.setAttribute("role", "option");
668
781
  listItem.setAttribute("aria-selected", String(isSelected));
669
- listItem.setAttribute("aria-label", ( localize(6557, "Option {0}: {1}", index + 1, option.label)));
782
+ listItem.setAttribute("aria-label", ( localize(6733, "Option {0}: {1}", index + 1, option.label)));
670
783
  listItem.id = `option-${question.id}-${index}`;
671
784
  listItem.tabIndex = -1;
672
785
  const number = $(".chat-question-list-number");
@@ -724,27 +837,36 @@ let ChatQuestionCarouselPart = class ChatQuestionCarouselPart extends Disposable
724
837
  if (selectedIndex >= 0 && selectedIndex < listItems.length) {
725
838
  selectContainer.setAttribute("aria-activedescendant", listItems[selectedIndex].id);
726
839
  }
727
- const freeformContainer = $(".chat-question-freeform");
728
- const freeformNumber = $(".chat-question-freeform-number");
729
- freeformNumber.textContent = `${options.length + 1}`;
730
- freeformContainer.appendChild(freeformNumber);
731
- const freeformTextarea = $("textarea.chat-question-freeform-textarea");
732
- freeformTextarea.placeholder = ( localize(6558, "Enter custom answer"));
733
- freeformTextarea.rows = 1;
734
- if (previousFreeform !== undefined) {
735
- freeformTextarea.value = previousFreeform;
736
- }
737
- const autoResize = this.setupTextareaAutoResize(freeformTextarea);
738
- this._inputBoxes.add(addDisposableListener(freeformTextarea, EventType.INPUT, () => {
739
- if (freeformTextarea.value.length > 0) {
740
- updateSelection(-1);
741
- } else {
742
- this.saveCurrentAnswer();
840
+ let freeformTextarea;
841
+ if (question.allowFreeformInput !== false) {
842
+ const freeformContainer = $(".chat-question-freeform");
843
+ const freeformNumber = $(".chat-question-freeform-number");
844
+ freeformNumber.textContent = `${options.length + 1}`;
845
+ freeformContainer.appendChild(freeformNumber);
846
+ freeformTextarea = $("textarea.chat-question-freeform-textarea");
847
+ freeformTextarea.placeholder = ( localize(6734, "Enter custom answer"));
848
+ freeformTextarea.rows = 1;
849
+ if (previousFreeform !== undefined) {
850
+ freeformTextarea.value = previousFreeform;
743
851
  }
744
- }));
745
- freeformContainer.appendChild(freeformTextarea);
746
- container.appendChild(freeformContainer);
747
- this._freeformTextareas.set(question.id, freeformTextarea);
852
+ const autoResize = this.setupTextareaAutoResize(freeformTextarea);
853
+ const capturedFreeform = freeformTextarea;
854
+ this._inputBoxes.add(addDisposableListener(capturedFreeform, EventType.INPUT, () => {
855
+ if (capturedFreeform.value.length > 0) {
856
+ updateSelection(-1);
857
+ } else {
858
+ this.saveCurrentAnswer();
859
+ }
860
+ }));
861
+ freeformContainer.appendChild(freeformTextarea);
862
+ container.appendChild(freeformContainer);
863
+ this._freeformTextareas.set(question.id, freeformTextarea);
864
+ if (previousFreeform !== undefined) {
865
+ this._inputBoxes.add(
866
+ runAtThisOrScheduleAtNextAnimationFrame(getWindow(capturedFreeform), () => autoResize())
867
+ );
868
+ }
869
+ }
748
870
  this._inputBoxes.add(addDisposableListener(selectContainer, EventType.KEY_DOWN, e => {
749
871
  const event = ( new StandardKeyboardEvent(e));
750
872
  const data = this._singleSelectItems.get(question.id);
@@ -768,7 +890,7 @@ let ChatQuestionCarouselPart = class ChatQuestionCarouselPart extends Disposable
768
890
  if (numberIndex < listItems.length) {
769
891
  e.preventDefault();
770
892
  updateSelection(numberIndex);
771
- } else if (numberIndex === listItems.length) {
893
+ } else if (freeformTextarea && numberIndex === listItems.length) {
772
894
  e.preventDefault();
773
895
  updateSelection(-1);
774
896
  freeformTextarea.focus();
@@ -779,16 +901,12 @@ let ChatQuestionCarouselPart = class ChatQuestionCarouselPart extends Disposable
779
901
  updateSelection(newIndex);
780
902
  }
781
903
  }));
782
- if (previousFreeform !== undefined) {
783
- this._inputBoxes.add(
784
- runAtThisOrScheduleAtNextAnimationFrame(getWindow(freeformTextarea), () => autoResize())
785
- );
786
- }
787
904
  if (this._shouldAutoFocus()) {
788
- if (previousFreeform) {
905
+ if (freeformTextarea && previousFreeform) {
906
+ const capturedFreeform = freeformTextarea;
789
907
  this._inputBoxes.add(
790
- runAtThisOrScheduleAtNextAnimationFrame(getWindow(freeformTextarea), () => {
791
- freeformTextarea.focus();
908
+ runAtThisOrScheduleAtNextAnimationFrame(getWindow(capturedFreeform), () => {
909
+ capturedFreeform.focus();
792
910
  })
793
911
  );
794
912
  } else if (listItems.length > 0) {
@@ -813,12 +931,11 @@ let ChatQuestionCarouselPart = class ChatQuestionCarouselPart extends Disposable
813
931
  selectContainer.tabIndex = 0;
814
932
  container.appendChild(selectContainer);
815
933
  const previousAnswer = this._answers.get(question.id);
816
- const previousFreeform = typeof previousAnswer === "object" && previousAnswer !== null && hasKey(previousAnswer, {
817
- freeformValue: true
818
- }) ? previousAnswer.freeformValue : undefined;
819
- const previousSelectedValues = typeof previousAnswer === "object" && previousAnswer !== null && hasKey(previousAnswer, {
934
+ const prevMulti = typeof previousAnswer === "object" && previousAnswer !== null && hasKey(previousAnswer, {
820
935
  selectedValues: true
821
- }) ? previousAnswer.selectedValues : (Array.isArray(previousAnswer) ? previousAnswer : []);
936
+ }) ? previousAnswer : undefined;
937
+ const previousFreeform = prevMulti?.freeformValue;
938
+ const previousSelectedValues = prevMulti?.selectedValues ?? [];
822
939
  const defaultOptionIds = Array.isArray(question.defaultValue) ? question.defaultValue : (typeof question.defaultValue === "string" ? [question.defaultValue] : []);
823
940
  const checkboxes = [];
824
941
  const listItems = [];
@@ -834,7 +951,7 @@ let ChatQuestionCarouselPart = class ChatQuestionCarouselPart extends Disposable
834
951
  const listItem = $(".chat-question-list-item.multi-select");
835
952
  listItem.setAttribute("role", "option");
836
953
  listItem.setAttribute("aria-selected", String(isChecked));
837
- listItem.setAttribute("aria-label", ( localize(6557, "Option {0}: {1}", index + 1, option.label)));
954
+ listItem.setAttribute("aria-label", ( localize(6733, "Option {0}: {1}", index + 1, option.label)));
838
955
  listItem.id = `option-${question.id}-${index}`;
839
956
  listItem.tabIndex = -1;
840
957
  const number = $(".chat-question-list-number");
@@ -889,23 +1006,31 @@ let ChatQuestionCarouselPart = class ChatQuestionCarouselPart extends Disposable
889
1006
  listItems.push(listItem);
890
1007
  });
891
1008
  this._multiSelectCheckboxes.set(question.id, checkboxes);
892
- const freeformContainer = $(".chat-question-freeform");
893
- const freeformNumber = $(".chat-question-freeform-number");
894
- freeformNumber.textContent = `${options.length + 1}`;
895
- freeformContainer.appendChild(freeformNumber);
896
- const freeformTextarea = $("textarea.chat-question-freeform-textarea");
897
- freeformTextarea.placeholder = ( localize(6558, "Enter custom answer"));
898
- freeformTextarea.rows = 1;
899
- if (previousFreeform !== undefined) {
900
- freeformTextarea.value = previousFreeform;
901
- }
902
- const autoResize = this.setupTextareaAutoResize(freeformTextarea);
903
- this._inputBoxes.add(
904
- addDisposableListener(freeformTextarea, EventType.INPUT, () => this.saveCurrentAnswer())
905
- );
906
- freeformContainer.appendChild(freeformTextarea);
907
- container.appendChild(freeformContainer);
908
- this._freeformTextareas.set(question.id, freeformTextarea);
1009
+ let freeformTextarea;
1010
+ if (question.allowFreeformInput !== false) {
1011
+ const freeformContainer = $(".chat-question-freeform");
1012
+ const freeformNumber = $(".chat-question-freeform-number");
1013
+ freeformNumber.textContent = `${options.length + 1}`;
1014
+ freeformContainer.appendChild(freeformNumber);
1015
+ freeformTextarea = $("textarea.chat-question-freeform-textarea");
1016
+ freeformTextarea.placeholder = ( localize(6734, "Enter custom answer"));
1017
+ freeformTextarea.rows = 1;
1018
+ if (previousFreeform !== undefined) {
1019
+ freeformTextarea.value = previousFreeform;
1020
+ }
1021
+ const autoResize = this.setupTextareaAutoResize(freeformTextarea);
1022
+ this._inputBoxes.add(
1023
+ addDisposableListener(freeformTextarea, EventType.INPUT, () => this.saveCurrentAnswer())
1024
+ );
1025
+ freeformContainer.appendChild(freeformTextarea);
1026
+ container.appendChild(freeformContainer);
1027
+ this._freeformTextareas.set(question.id, freeformTextarea);
1028
+ if (previousFreeform !== undefined) {
1029
+ this._inputBoxes.add(
1030
+ runAtThisOrScheduleAtNextAnimationFrame(getWindow(freeformTextarea), () => autoResize())
1031
+ );
1032
+ }
1033
+ }
909
1034
  this._inputBoxes.add(addDisposableListener(selectContainer, EventType.KEY_DOWN, e => {
910
1035
  const event = ( new StandardKeyboardEvent(e));
911
1036
  if (!listItems.length) {
@@ -933,22 +1058,18 @@ let ChatQuestionCarouselPart = class ChatQuestionCarouselPart extends Disposable
933
1058
  if (numberIndex < checkboxes.length) {
934
1059
  e.preventDefault();
935
1060
  checkboxes[numberIndex].domNode.click();
936
- } else if (numberIndex === checkboxes.length) {
1061
+ } else if (freeformTextarea && numberIndex === checkboxes.length) {
937
1062
  e.preventDefault();
938
1063
  freeformTextarea.focus();
939
1064
  }
940
1065
  }
941
1066
  }));
942
- if (previousFreeform !== undefined) {
943
- this._inputBoxes.add(
944
- runAtThisOrScheduleAtNextAnimationFrame(getWindow(freeformTextarea), () => autoResize())
945
- );
946
- }
947
1067
  if (this._shouldAutoFocus()) {
948
- if (previousFreeform) {
1068
+ if (freeformTextarea && previousFreeform) {
1069
+ const capturedFreeform = freeformTextarea;
949
1070
  this._inputBoxes.add(
950
- runAtThisOrScheduleAtNextAnimationFrame(getWindow(freeformTextarea), () => {
951
- freeformTextarea.focus();
1071
+ runAtThisOrScheduleAtNextAnimationFrame(getWindow(capturedFreeform), () => {
1072
+ capturedFreeform.focus();
952
1073
  })
953
1074
  );
954
1075
  } else if (listItems.length > 0) {
@@ -971,7 +1092,9 @@ let ChatQuestionCarouselPart = class ChatQuestionCarouselPart extends Disposable
971
1092
  case "text":
972
1093
  {
973
1094
  const inputBox = this._textInputBoxes.get(question.id);
974
- return inputBox?.value ?? question.defaultValue;
1095
+ return inputBox?.value ?? (typeof question.defaultValue === "string" ? question.defaultValue : Array.isArray(question.defaultValue) ? {
1096
+ selectedValues: question.defaultValue
1097
+ } : undefined);
975
1098
  }
976
1099
  case "singleSelect":
977
1100
  {
@@ -1025,13 +1148,15 @@ let ChatQuestionCarouselPart = class ChatQuestionCarouselPart extends Disposable
1025
1148
  return undefined;
1026
1149
  }
1027
1150
  default:
1028
- return question.defaultValue;
1151
+ return typeof question.defaultValue === "string" ? question.defaultValue : Array.isArray(question.defaultValue) ? {
1152
+ selectedValues: question.defaultValue
1153
+ } : undefined;
1029
1154
  }
1030
1155
  }
1031
1156
  renderSkippedMessage() {
1032
1157
  const skippedContainer = $(".chat-question-carousel-summary");
1033
1158
  const skippedMessage = $(".chat-question-summary-skipped");
1034
- skippedMessage.textContent = ( localize(6559, "Skipped"));
1159
+ skippedMessage.textContent = ( localize(6735, "Skipped"));
1035
1160
  skippedContainer.appendChild(skippedMessage);
1036
1161
  this.domNode.appendChild(skippedContainer);
1037
1162
  }
@@ -1050,16 +1175,16 @@ let ChatQuestionCarouselPart = class ChatQuestionCarouselPart extends Disposable
1050
1175
  const questionText = question.message ?? question.title;
1051
1176
  let labelText = typeof questionText === "string" ? questionText : questionText.value;
1052
1177
  labelText = labelText.replace(/[:\s]+$/, "");
1053
- questionRow.textContent = ( localize(6560, "Q: {0}", labelText));
1178
+ questionRow.textContent = ( localize(6736, "Q: {0}", labelText));
1054
1179
  summaryItem.appendChild(questionRow);
1055
1180
  if (answer !== undefined) {
1056
1181
  const formattedAnswer = this.formatAnswerForSummary(question, answer);
1057
1182
  const answerRow = $("div.chat-question-summary-answer-title");
1058
- answerRow.textContent = ( localize(6561, "A: {0}", formattedAnswer));
1183
+ answerRow.textContent = ( localize(6737, "A: {0}", formattedAnswer));
1059
1184
  summaryItem.appendChild(answerRow);
1060
1185
  } else {
1061
1186
  const unanswered = $("div.chat-question-summary-unanswered");
1062
- unanswered.textContent = ( localize(6562, "Not answered yet"));
1187
+ unanswered.textContent = ( localize(6738, "Not answered yet"));
1063
1188
  summaryItem.appendChild(unanswered);
1064
1189
  }
1065
1190
  summaryContainer.appendChild(summaryItem);
@@ -1072,44 +1197,34 @@ let ChatQuestionCarouselPart = class ChatQuestionCarouselPart extends Disposable
1072
1197
  return String(answer);
1073
1198
  case "singleSelect":
1074
1199
  {
1075
- if (typeof answer === "object" && answer !== null && hasKey(answer, {
1076
- selectedValue: true
1077
- })) {
1200
+ if (typeof answer === "object") {
1078
1201
  const {
1079
1202
  selectedValue,
1080
1203
  freeformValue
1081
1204
  } = answer;
1082
- const selectedLabel = question.options?.find(opt => opt.value === selectedValue)?.label;
1205
+ const selectedLabel = selectedValue !== undefined ? question.options?.find(opt => opt.value === selectedValue)?.label : undefined;
1083
1206
  if (freeformValue) {
1084
1207
  return freeformValue;
1085
1208
  }
1086
1209
  return selectedLabel ?? String(selectedValue ?? "");
1087
1210
  }
1088
- if (typeof answer === "object" && answer !== null && hasKey(answer, {
1089
- freeformValue: true
1090
- })) {
1091
- return answer.freeformValue ?? "";
1092
- }
1093
1211
  const label = question.options?.find(opt => opt.value === answer)?.label;
1094
1212
  return label ?? String(answer);
1095
1213
  }
1096
1214
  case "multiSelect":
1097
1215
  {
1098
- if (typeof answer === "object" && answer !== null && hasKey(answer, {
1216
+ if (typeof answer === "object" && hasKey(answer, {
1099
1217
  selectedValues: true
1100
1218
  })) {
1101
1219
  const {
1102
1220
  selectedValues,
1103
1221
  freeformValue
1104
1222
  } = answer;
1105
- const labels = ( (selectedValues ?? []).map(v => question.options?.find(opt => opt.value === v)?.label ?? String(v)));
1223
+ const labels = ( selectedValues.map(v => question.options?.find(opt => opt.value === v)?.label ?? String(v)));
1106
1224
  if (freeformValue) {
1107
1225
  labels.push(freeformValue);
1108
1226
  }
1109
- return labels.join(( localize(6563, ", ")));
1110
- }
1111
- if (Array.isArray(answer)) {
1112
- return ( answer.map(v => question.options?.find(opt => opt.value === v)?.label ?? String(v))).join(( localize(6563, ", ")));
1227
+ return labels.join(( localize(6739, ", ")));
1113
1228
  }
1114
1229
  return String(answer);
1115
1230
  }
@@ -1121,6 +1236,109 @@ let ChatQuestionCarouselPart = class ChatQuestionCarouselPart extends Disposable
1121
1236
  const md = typeof questionText === "string" ? ( new MarkdownString(questionText)) : questionText;
1122
1237
  return renderAsPlaintext(md);
1123
1238
  }
1239
+ validateCurrentQuestion() {
1240
+ const question = this.carousel.questions[this._currentIndex];
1241
+ if (!question) {
1242
+ return true;
1243
+ }
1244
+ const answer = this._answers.get(question.id);
1245
+ if (question.required && (answer === undefined || answer === "")) {
1246
+ this.showValidationError(( localize(6740, "This field is required")));
1247
+ return false;
1248
+ }
1249
+ if (question.type === "text" && question.validation && typeof answer === "string" && answer !== "") {
1250
+ const error = this.getValidationError(answer, question.validation);
1251
+ if (error) {
1252
+ this.showValidationError(error);
1253
+ return false;
1254
+ }
1255
+ }
1256
+ this.clearValidationError();
1257
+ return true;
1258
+ }
1259
+ validateRequiredFields() {
1260
+ for (let i = 0; i < this.carousel.questions.length; i++) {
1261
+ const question = this.carousel.questions[i];
1262
+ if (!question.required) {
1263
+ continue;
1264
+ }
1265
+ const answer = this._answers.get(question.id);
1266
+ if (answer === undefined || answer === "") {
1267
+ this.saveCurrentAnswer();
1268
+ this._currentIndex = i;
1269
+ this.persistDraftState();
1270
+ this.renderCurrentQuestion(true);
1271
+ this.showValidationError(( localize(6740, "This field is required")));
1272
+ return false;
1273
+ }
1274
+ }
1275
+ return true;
1276
+ }
1277
+ getValidationError(value, validation) {
1278
+ if (validation.minLength !== undefined && value.length < validation.minLength) {
1279
+ return localize(6741, "Minimum length is {0}", validation.minLength);
1280
+ }
1281
+ if (validation.maxLength !== undefined && value.length > validation.maxLength) {
1282
+ return localize(6742, "Maximum length is {0}", validation.maxLength);
1283
+ }
1284
+ if (validation.format) {
1285
+ switch (validation.format) {
1286
+ case "email":
1287
+ if (!value.includes("@")) {
1288
+ return localize(6743, "Please enter a valid email address");
1289
+ }
1290
+ break;
1291
+ case "uri":
1292
+ if (!URL.canParse(value)) {
1293
+ return localize(6744, "Please enter a valid URI");
1294
+ }
1295
+ break;
1296
+ case "date":
1297
+ {
1298
+ const dateRegex = /^\d{4}-\d{2}-\d{2}$/;
1299
+ if (!dateRegex.test(value) || isNaN(( new Date(value)).getTime())) {
1300
+ return localize(6745, "Please enter a valid date (YYYY-MM-DD)");
1301
+ }
1302
+ break;
1303
+ }
1304
+ case "date-time":
1305
+ if (isNaN(( new Date(value)).getTime())) {
1306
+ return localize(6746, "Please enter a valid date-time");
1307
+ }
1308
+ break;
1309
+ }
1310
+ }
1311
+ if (validation.isInteger !== undefined || validation.minimum !== undefined || validation.maximum !== undefined) {
1312
+ const num = Number(value);
1313
+ if (isNaN(num)) {
1314
+ return localize(6747, "Please enter a valid number");
1315
+ }
1316
+ if (validation.isInteger && !Number.isInteger(num)) {
1317
+ return localize(6748, "Please enter a valid integer");
1318
+ }
1319
+ if (validation.minimum !== undefined && num < validation.minimum) {
1320
+ return localize(6749, "Minimum value is {0}", validation.minimum);
1321
+ }
1322
+ if (validation.maximum !== undefined && num > validation.maximum) {
1323
+ return localize(6750, "Maximum value is {0}", validation.maximum);
1324
+ }
1325
+ }
1326
+ return undefined;
1327
+ }
1328
+ showValidationError(message) {
1329
+ this._currentValidationError = message;
1330
+ if (this._validationMessageElement) {
1331
+ this._validationMessageElement.textContent = message;
1332
+ this._validationMessageElement.style.display = "";
1333
+ }
1334
+ }
1335
+ clearValidationError() {
1336
+ this._currentValidationError = undefined;
1337
+ if (this._validationMessageElement) {
1338
+ this._validationMessageElement.textContent = "";
1339
+ this._validationMessageElement.style.display = "none";
1340
+ }
1341
+ }
1124
1342
  hasSameContent(other, _followingContent, element) {
1125
1343
  if (!this._isSkipped && !this.carousel.isUsed && isResponseVM(element) && element.isComplete) {
1126
1344
  return false;