@patternfly/chatbot 6.5.0-prerelease.3 → 6.5.0-prerelease.30

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 (351) hide show
  1. package/dist/cjs/AttachMenu/AttachMenu.d.ts +8 -2
  2. package/dist/cjs/AttachMenu/AttachMenu.js +2 -2
  3. package/dist/cjs/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.d.ts +9 -1
  4. package/dist/cjs/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.js +9 -2
  5. package/dist/cjs/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.test.js +38 -0
  6. package/dist/cjs/ChatbotFooter/ChatbotFooter.d.ts +5 -2
  7. package/dist/cjs/ChatbotFooter/ChatbotFooter.js +2 -2
  8. package/dist/cjs/ChatbotFooter/ChatbotFooter.test.js +5 -1
  9. package/dist/cjs/ChatbotHeader/ChatbotHeaderMenu.js +29 -2
  10. package/dist/cjs/CodeModal/CodeModal.d.ts +2 -0
  11. package/dist/cjs/CodeModal/CodeModal.js +53 -8
  12. package/dist/cjs/DeepThinking/DeepThinking.d.ts +13 -0
  13. package/dist/cjs/DeepThinking/DeepThinking.js +31 -3
  14. package/dist/cjs/DeepThinking/DeepThinking.test.js +80 -0
  15. package/dist/cjs/FileDetailsLabel/FileDetailsLabel.d.ts +2 -1
  16. package/dist/cjs/MarkdownContent/MarkdownContent.d.ts +44 -0
  17. package/dist/cjs/MarkdownContent/MarkdownContent.js +181 -0
  18. package/dist/cjs/MarkdownContent/MarkdownContent.test.d.ts +1 -0
  19. package/dist/cjs/MarkdownContent/MarkdownContent.test.js +192 -0
  20. package/dist/cjs/MarkdownContent/index.d.ts +2 -0
  21. package/dist/cjs/MarkdownContent/index.js +23 -0
  22. package/dist/cjs/Message/CodeBlockMessage/CodeBlockMessage.d.ts +5 -1
  23. package/dist/cjs/Message/CodeBlockMessage/CodeBlockMessage.js +16 -5
  24. package/dist/cjs/Message/CodeBlockMessage/CodeBlockMessage.test.d.ts +1 -0
  25. package/dist/cjs/Message/CodeBlockMessage/CodeBlockMessage.test.js +131 -0
  26. package/dist/cjs/Message/ErrorMessage/ErrorMessage.d.ts +15 -1
  27. package/dist/cjs/Message/ErrorMessage/ErrorMessage.js +5 -3
  28. package/dist/cjs/Message/ErrorMessage/ErrorMessage.test.d.ts +1 -0
  29. package/dist/cjs/Message/ErrorMessage/ErrorMessage.test.js +30 -0
  30. package/dist/cjs/Message/LinkMessage/LinkMessage.d.ts +5 -1
  31. package/dist/cjs/Message/LinkMessage/LinkMessage.js +4 -3
  32. package/dist/cjs/Message/ListMessage/OrderedListMessage.d.ts +9 -1
  33. package/dist/cjs/Message/ListMessage/OrderedListMessage.js +2 -1
  34. package/dist/cjs/Message/ListMessage/UnorderedListMessage.d.ts +7 -1
  35. package/dist/cjs/Message/ListMessage/UnorderedListMessage.js +2 -1
  36. package/dist/cjs/Message/Message.d.ts +22 -3
  37. package/dist/cjs/Message/Message.js +8 -161
  38. package/dist/cjs/Message/Message.test.js +161 -2
  39. package/dist/cjs/Message/MessageAndActions/MessageAndActions.d.ts +14 -0
  40. package/dist/cjs/Message/MessageAndActions/MessageAndActions.js +22 -0
  41. package/dist/cjs/Message/MessageAndActions/MessageAndActions.test.d.ts +1 -0
  42. package/dist/cjs/Message/MessageAndActions/MessageAndActions.test.js +25 -0
  43. package/dist/cjs/Message/MessageAndActions/index.d.ts +1 -0
  44. package/dist/cjs/Message/MessageAndActions/index.js +17 -0
  45. package/dist/cjs/Message/MessageAttachments/MessageAttachmentItem.d.ts +13 -0
  46. package/dist/cjs/Message/MessageAttachments/MessageAttachmentItem.js +22 -0
  47. package/dist/cjs/Message/MessageAttachments/MessageAttachmentItem.test.d.ts +1 -0
  48. package/dist/cjs/Message/MessageAttachments/MessageAttachmentItem.test.js +25 -0
  49. package/dist/cjs/Message/MessageAttachments/MessageAttachmentsContainer.d.ts +13 -0
  50. package/dist/cjs/Message/MessageAttachments/MessageAttachmentsContainer.js +22 -0
  51. package/dist/cjs/Message/MessageAttachments/MessageAttachmentsContainer.test.d.ts +1 -0
  52. package/dist/cjs/Message/MessageAttachments/MessageAttachmentsContainer.test.js +25 -0
  53. package/dist/cjs/Message/MessageAttachments/index.d.ts +2 -0
  54. package/dist/cjs/Message/MessageAttachments/index.js +18 -0
  55. package/dist/cjs/Message/MessageInput.d.ts +1 -1
  56. package/dist/cjs/Message/MessageInput.js +3 -1
  57. package/dist/cjs/Message/MessageLoading.d.ts +13 -3
  58. package/dist/cjs/Message/MessageLoading.js +19 -5
  59. package/dist/cjs/Message/MessageLoading.test.d.ts +1 -0
  60. package/dist/cjs/Message/MessageLoading.test.js +25 -0
  61. package/dist/cjs/Message/QuickResponse/QuickResponse.js +3 -2
  62. package/dist/cjs/Message/QuickResponse/QuickResponse.test.d.ts +1 -0
  63. package/dist/cjs/Message/QuickResponse/QuickResponse.test.js +109 -0
  64. package/dist/cjs/Message/QuickResponse/index.d.ts +1 -0
  65. package/dist/cjs/Message/QuickResponse/index.js +17 -0
  66. package/dist/cjs/Message/QuickStarts/QuickStartTile.d.ts +1 -1
  67. package/dist/cjs/Message/QuickStarts/QuickStartTile.js +3 -2
  68. package/dist/cjs/Message/QuickStarts/index.d.ts +2 -0
  69. package/dist/cjs/Message/QuickStarts/index.js +18 -0
  70. package/dist/cjs/Message/TableMessage/TableMessage.d.ts +9 -1
  71. package/dist/cjs/Message/TableMessage/TableMessage.js +3 -2
  72. package/dist/cjs/Message/TextMessage/TextMessage.d.ts +11 -1
  73. package/dist/cjs/Message/TextMessage/TextMessage.js +3 -2
  74. package/dist/cjs/Message/UserFeedback/UserFeedback.d.ts +3 -1
  75. package/dist/cjs/Message/UserFeedback/UserFeedback.js +8 -6
  76. package/dist/cjs/Message/UserFeedback/UserFeedbackComplete.d.ts +1 -1
  77. package/dist/cjs/Message/UserFeedback/UserFeedbackComplete.js +3 -2
  78. package/dist/cjs/Message/UserFeedback/index.d.ts +2 -0
  79. package/dist/cjs/Message/UserFeedback/index.js +18 -0
  80. package/dist/cjs/Message/index.d.ts +8 -0
  81. package/dist/cjs/Message/index.js +8 -0
  82. package/dist/cjs/MessageBar/AttachButton.d.ts +2 -0
  83. package/dist/cjs/MessageBar/AttachButton.js +2 -2
  84. package/dist/cjs/MessageBar/AttachButton.test.js +4 -0
  85. package/dist/cjs/MessageBar/MessageBar.d.ts +22 -6
  86. package/dist/cjs/MessageBar/MessageBar.js +43 -11
  87. package/dist/cjs/MessageBar/MessageBar.test.js +74 -0
  88. package/dist/cjs/Onboarding/Onboarding.d.ts +36 -0
  89. package/dist/cjs/Onboarding/Onboarding.js +37 -0
  90. package/dist/cjs/Onboarding/Onboarding.test.d.ts +1 -0
  91. package/dist/cjs/Onboarding/Onboarding.test.js +80 -0
  92. package/dist/cjs/Onboarding/index.d.ts +2 -0
  93. package/dist/cjs/Onboarding/index.js +23 -0
  94. package/dist/cjs/ResponseActions/ResponseActions.d.ts +7 -0
  95. package/dist/cjs/ResponseActions/ResponseActions.js +28 -7
  96. package/dist/cjs/ResponseActions/ResponseActions.test.js +67 -12
  97. package/dist/cjs/ResponseActions/ResponseActionsGroups.d.ts +13 -0
  98. package/dist/cjs/ResponseActions/ResponseActionsGroups.js +22 -0
  99. package/dist/cjs/ResponseActions/ResponseActionsGroups.test.d.ts +1 -0
  100. package/dist/cjs/ResponseActions/ResponseActionsGroups.test.js +25 -0
  101. package/dist/cjs/ResponseActions/index.d.ts +1 -0
  102. package/dist/cjs/ResponseActions/index.js +1 -0
  103. package/dist/cjs/ToolCall/ToolCall.d.ts +11 -0
  104. package/dist/cjs/ToolCall/ToolCall.js +24 -3
  105. package/dist/cjs/ToolCall/ToolCall.test.js +57 -0
  106. package/dist/cjs/ToolResponse/ToolResponse.d.ts +17 -0
  107. package/dist/cjs/ToolResponse/ToolResponse.js +49 -3
  108. package/dist/cjs/ToolResponse/ToolResponse.test.js +100 -0
  109. package/dist/cjs/__mocks__/monaco-editor.d.ts +11 -0
  110. package/dist/cjs/__mocks__/monaco-editor.js +18 -0
  111. package/dist/cjs/index.d.ts +4 -0
  112. package/dist/cjs/index.js +7 -1
  113. package/dist/css/main.css +336 -30
  114. package/dist/css/main.css.map +1 -1
  115. package/dist/dynamic/MarkdownContent/package.json +1 -0
  116. package/dist/dynamic/Onboarding/package.json +1 -0
  117. package/dist/esm/AttachMenu/AttachMenu.d.ts +8 -2
  118. package/dist/esm/AttachMenu/AttachMenu.js +2 -2
  119. package/dist/esm/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.d.ts +9 -1
  120. package/dist/esm/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.js +10 -3
  121. package/dist/esm/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.test.js +38 -0
  122. package/dist/esm/ChatbotFooter/ChatbotFooter.d.ts +5 -2
  123. package/dist/esm/ChatbotFooter/ChatbotFooter.js +2 -2
  124. package/dist/esm/ChatbotFooter/ChatbotFooter.test.js +5 -1
  125. package/dist/esm/ChatbotHeader/ChatbotHeaderMenu.js +30 -3
  126. package/dist/esm/CodeModal/CodeModal.d.ts +2 -0
  127. package/dist/esm/CodeModal/CodeModal.js +54 -9
  128. package/dist/esm/DeepThinking/DeepThinking.d.ts +13 -0
  129. package/dist/esm/DeepThinking/DeepThinking.js +28 -3
  130. package/dist/esm/DeepThinking/DeepThinking.test.js +80 -0
  131. package/dist/esm/FileDetailsLabel/FileDetailsLabel.d.ts +2 -1
  132. package/dist/esm/MarkdownContent/MarkdownContent.d.ts +44 -0
  133. package/dist/esm/MarkdownContent/MarkdownContent.js +174 -0
  134. package/dist/esm/MarkdownContent/MarkdownContent.test.d.ts +1 -0
  135. package/dist/esm/MarkdownContent/MarkdownContent.test.js +187 -0
  136. package/dist/esm/MarkdownContent/index.d.ts +2 -0
  137. package/dist/esm/MarkdownContent/index.js +2 -0
  138. package/dist/esm/Message/CodeBlockMessage/CodeBlockMessage.d.ts +5 -1
  139. package/dist/esm/Message/CodeBlockMessage/CodeBlockMessage.js +16 -5
  140. package/dist/esm/Message/CodeBlockMessage/CodeBlockMessage.test.d.ts +1 -0
  141. package/dist/esm/Message/CodeBlockMessage/CodeBlockMessage.test.js +126 -0
  142. package/dist/esm/Message/ErrorMessage/ErrorMessage.d.ts +15 -1
  143. package/dist/esm/Message/ErrorMessage/ErrorMessage.js +3 -3
  144. package/dist/esm/Message/ErrorMessage/ErrorMessage.test.d.ts +1 -0
  145. package/dist/esm/Message/ErrorMessage/ErrorMessage.test.js +25 -0
  146. package/dist/esm/Message/LinkMessage/LinkMessage.d.ts +5 -1
  147. package/dist/esm/Message/LinkMessage/LinkMessage.js +4 -3
  148. package/dist/esm/Message/ListMessage/OrderedListMessage.d.ts +9 -1
  149. package/dist/esm/Message/ListMessage/OrderedListMessage.js +2 -1
  150. package/dist/esm/Message/ListMessage/UnorderedListMessage.d.ts +7 -1
  151. package/dist/esm/Message/ListMessage/UnorderedListMessage.js +2 -1
  152. package/dist/esm/Message/Message.d.ts +22 -3
  153. package/dist/esm/Message/Message.js +9 -162
  154. package/dist/esm/Message/Message.test.js +161 -2
  155. package/dist/esm/Message/MessageAndActions/MessageAndActions.d.ts +14 -0
  156. package/dist/esm/Message/MessageAndActions/MessageAndActions.js +18 -0
  157. package/dist/esm/Message/MessageAndActions/MessageAndActions.test.d.ts +1 -0
  158. package/dist/esm/Message/MessageAndActions/MessageAndActions.test.js +20 -0
  159. package/dist/esm/Message/MessageAndActions/index.d.ts +1 -0
  160. package/dist/esm/Message/MessageAndActions/index.js +1 -0
  161. package/dist/esm/Message/MessageAttachments/MessageAttachmentItem.d.ts +13 -0
  162. package/dist/esm/Message/MessageAttachments/MessageAttachmentItem.js +18 -0
  163. package/dist/esm/Message/MessageAttachments/MessageAttachmentItem.test.d.ts +1 -0
  164. package/dist/esm/Message/MessageAttachments/MessageAttachmentItem.test.js +20 -0
  165. package/dist/esm/Message/MessageAttachments/MessageAttachmentsContainer.d.ts +13 -0
  166. package/dist/esm/Message/MessageAttachments/MessageAttachmentsContainer.js +18 -0
  167. package/dist/esm/Message/MessageAttachments/MessageAttachmentsContainer.test.d.ts +1 -0
  168. package/dist/esm/Message/MessageAttachments/MessageAttachmentsContainer.test.js +20 -0
  169. package/dist/esm/Message/MessageAttachments/index.d.ts +2 -0
  170. package/dist/esm/Message/MessageAttachments/index.js +2 -0
  171. package/dist/esm/Message/MessageInput.d.ts +1 -1
  172. package/dist/esm/Message/MessageInput.js +1 -1
  173. package/dist/esm/Message/MessageLoading.d.ts +13 -3
  174. package/dist/esm/Message/MessageLoading.js +16 -4
  175. package/dist/esm/Message/MessageLoading.test.d.ts +1 -0
  176. package/dist/esm/Message/MessageLoading.test.js +20 -0
  177. package/dist/esm/Message/QuickResponse/QuickResponse.js +3 -2
  178. package/dist/esm/Message/QuickResponse/QuickResponse.test.d.ts +1 -0
  179. package/dist/esm/Message/QuickResponse/QuickResponse.test.js +104 -0
  180. package/dist/esm/Message/QuickResponse/index.d.ts +1 -0
  181. package/dist/esm/Message/QuickResponse/index.js +1 -0
  182. package/dist/esm/Message/QuickStarts/QuickStartTile.d.ts +1 -1
  183. package/dist/esm/Message/QuickStarts/QuickStartTile.js +1 -1
  184. package/dist/esm/Message/QuickStarts/index.d.ts +2 -0
  185. package/dist/esm/Message/QuickStarts/index.js +2 -0
  186. package/dist/esm/Message/TableMessage/TableMessage.d.ts +9 -1
  187. package/dist/esm/Message/TableMessage/TableMessage.js +3 -2
  188. package/dist/esm/Message/TextMessage/TextMessage.d.ts +11 -1
  189. package/dist/esm/Message/TextMessage/TextMessage.js +3 -2
  190. package/dist/esm/Message/UserFeedback/UserFeedback.d.ts +3 -1
  191. package/dist/esm/Message/UserFeedback/UserFeedback.js +7 -7
  192. package/dist/esm/Message/UserFeedback/UserFeedbackComplete.d.ts +1 -1
  193. package/dist/esm/Message/UserFeedback/UserFeedbackComplete.js +1 -2
  194. package/dist/esm/Message/UserFeedback/index.d.ts +2 -0
  195. package/dist/esm/Message/UserFeedback/index.js +2 -0
  196. package/dist/esm/Message/index.d.ts +8 -0
  197. package/dist/esm/Message/index.js +8 -0
  198. package/dist/esm/MessageBar/AttachButton.d.ts +2 -0
  199. package/dist/esm/MessageBar/AttachButton.js +2 -2
  200. package/dist/esm/MessageBar/AttachButton.test.js +4 -0
  201. package/dist/esm/MessageBar/MessageBar.d.ts +22 -6
  202. package/dist/esm/MessageBar/MessageBar.js +43 -11
  203. package/dist/esm/MessageBar/MessageBar.test.js +74 -0
  204. package/dist/esm/Onboarding/Onboarding.d.ts +36 -0
  205. package/dist/esm/Onboarding/Onboarding.js +30 -0
  206. package/dist/esm/Onboarding/Onboarding.test.d.ts +1 -0
  207. package/dist/esm/Onboarding/Onboarding.test.js +75 -0
  208. package/dist/esm/Onboarding/index.d.ts +2 -0
  209. package/dist/esm/Onboarding/index.js +2 -0
  210. package/dist/esm/ResponseActions/ResponseActions.d.ts +7 -0
  211. package/dist/esm/ResponseActions/ResponseActions.js +28 -7
  212. package/dist/esm/ResponseActions/ResponseActions.test.js +67 -12
  213. package/dist/esm/ResponseActions/ResponseActionsGroups.d.ts +13 -0
  214. package/dist/esm/ResponseActions/ResponseActionsGroups.js +18 -0
  215. package/dist/esm/ResponseActions/ResponseActionsGroups.test.d.ts +1 -0
  216. package/dist/esm/ResponseActions/ResponseActionsGroups.test.js +20 -0
  217. package/dist/esm/ResponseActions/index.d.ts +1 -0
  218. package/dist/esm/ResponseActions/index.js +1 -0
  219. package/dist/esm/ToolCall/ToolCall.d.ts +11 -0
  220. package/dist/esm/ToolCall/ToolCall.js +21 -3
  221. package/dist/esm/ToolCall/ToolCall.test.js +57 -0
  222. package/dist/esm/ToolResponse/ToolResponse.d.ts +17 -0
  223. package/dist/esm/ToolResponse/ToolResponse.js +46 -3
  224. package/dist/esm/ToolResponse/ToolResponse.test.js +100 -0
  225. package/dist/esm/__mocks__/monaco-editor.d.ts +11 -0
  226. package/dist/esm/__mocks__/monaco-editor.js +18 -0
  227. package/dist/esm/index.d.ts +4 -0
  228. package/dist/esm/index.js +4 -0
  229. package/dist/tsconfig.tsbuildinfo +1 -1
  230. package/package.json +13 -2
  231. package/patternfly-docs/content/extensions/chatbot/chatbot.md +57 -0
  232. package/patternfly-docs/content/extensions/chatbot/design-guidelines.md +12 -12
  233. package/patternfly-docs/content/extensions/chatbot/examples/Analytics/Analytics.md +1 -1
  234. package/patternfly-docs/content/extensions/chatbot/examples/Customizing Messages/Customizing Messages.md +1 -1
  235. package/patternfly-docs/content/extensions/chatbot/examples/Messages/BotMessage.tsx +1 -0
  236. package/patternfly-docs/content/extensions/chatbot/examples/Messages/MessageWithCustomStructure.tsx +102 -0
  237. package/patternfly-docs/content/extensions/chatbot/examples/Messages/MessageWithDeepThinking.tsx +25 -11
  238. package/patternfly-docs/content/extensions/chatbot/examples/Messages/MessageWithFeedback.tsx +14 -1
  239. package/patternfly-docs/content/extensions/chatbot/examples/Messages/MessageWithMarkdownDeepThinking.tsx +26 -0
  240. package/patternfly-docs/content/extensions/chatbot/examples/Messages/MessageWithMarkdownToolCall.tsx +29 -0
  241. package/patternfly-docs/content/extensions/chatbot/examples/Messages/MessageWithMarkdownToolResponse.tsx +200 -0
  242. package/patternfly-docs/content/extensions/chatbot/examples/Messages/MessageWithMultipleActionGroups.tsx +61 -0
  243. package/patternfly-docs/content/extensions/chatbot/examples/Messages/MessageWithPersistedActions.tsx +22 -0
  244. package/patternfly-docs/content/extensions/chatbot/examples/Messages/MessageWithQuickResponses.tsx +11 -0
  245. package/patternfly-docs/content/extensions/chatbot/examples/Messages/MessageWithToolCall.tsx +14 -1
  246. package/patternfly-docs/content/extensions/chatbot/examples/Messages/MessageWithToolResponse.tsx +222 -105
  247. package/patternfly-docs/content/extensions/chatbot/examples/Messages/Messages.md +123 -14
  248. package/patternfly-docs/content/extensions/chatbot/examples/Messages/UserMessage.tsx +1 -0
  249. package/patternfly-docs/content/extensions/chatbot/examples/Messages/UserMessageWithExtraContent.tsx +3 -1
  250. package/patternfly-docs/content/extensions/chatbot/examples/UI/ChatbotHeaderDrawerWithSearchActions.tsx +198 -0
  251. package/patternfly-docs/content/extensions/chatbot/examples/UI/ChatbotMessageBarCustomActions.tsx +190 -0
  252. package/patternfly-docs/content/extensions/chatbot/examples/UI/ChatbotMessageBarIndicatorThinking.tsx +15 -0
  253. package/patternfly-docs/content/extensions/chatbot/examples/UI/CompactOnboarding.tsx +141 -0
  254. package/patternfly-docs/content/extensions/chatbot/examples/UI/Onboarding.tsx +151 -0
  255. package/patternfly-docs/content/extensions/chatbot/examples/UI/RH-Hat-Image.svg +9 -0
  256. package/patternfly-docs/content/extensions/chatbot/examples/UI/Settings.tsx +1 -1
  257. package/patternfly-docs/content/extensions/chatbot/examples/UI/UI.md +81 -30
  258. package/patternfly-docs/content/extensions/chatbot/examples/demos/AttachmentDemos.md +18 -18
  259. package/patternfly-docs/content/extensions/chatbot/examples/demos/Chatbot.md +44 -22
  260. package/patternfly-docs/content/extensions/chatbot/examples/demos/WhiteEmbeddedChatbot.tsx +451 -0
  261. package/patternfly-docs/patternfly-docs.config.js +1 -1
  262. package/patternfly-docs/patternfly-docs.source.js +1 -1
  263. package/src/AttachMenu/AttachMenu.tsx +26 -11
  264. package/src/Chatbot/Chatbot.scss +23 -1
  265. package/src/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.scss +43 -0
  266. package/src/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.test.tsx +95 -0
  267. package/src/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.tsx +51 -15
  268. package/src/ChatbotFooter/ChatbotFooter.scss +21 -0
  269. package/src/ChatbotFooter/ChatbotFooter.test.tsx +10 -1
  270. package/src/ChatbotFooter/ChatbotFooter.tsx +10 -3
  271. package/src/ChatbotHeader/ChatbotHeader.scss +19 -0
  272. package/src/ChatbotHeader/ChatbotHeaderMenu.tsx +56 -14
  273. package/src/ChatbotModal/ChatbotModal.scss +3 -0
  274. package/src/CodeModal/CodeModal.tsx +72 -23
  275. package/src/DeepThinking/DeepThinking.scss +1 -1
  276. package/src/DeepThinking/DeepThinking.test.tsx +109 -0
  277. package/src/DeepThinking/DeepThinking.tsx +54 -5
  278. package/src/FileDetailsLabel/FileDetailsLabel.tsx +2 -2
  279. package/src/MarkdownContent/MarkdownContent.test.tsx +207 -0
  280. package/src/MarkdownContent/MarkdownContent.tsx +269 -0
  281. package/src/MarkdownContent/index.ts +2 -0
  282. package/src/Message/CodeBlockMessage/CodeBlockMessage.scss +17 -0
  283. package/src/Message/CodeBlockMessage/CodeBlockMessage.test.tsx +171 -0
  284. package/src/Message/CodeBlockMessage/CodeBlockMessage.tsx +21 -5
  285. package/src/Message/ErrorMessage/ErrorMessage.test.tsx +38 -0
  286. package/src/Message/ErrorMessage/ErrorMessage.tsx +17 -2
  287. package/src/Message/LinkMessage/LinkMessage.scss +5 -0
  288. package/src/Message/LinkMessage/LinkMessage.tsx +24 -2
  289. package/src/Message/ListMessage/ListMessage.scss +8 -0
  290. package/src/Message/ListMessage/OrderedListMessage.tsx +16 -2
  291. package/src/Message/ListMessage/UnorderedListMessage.tsx +12 -2
  292. package/src/Message/Message.scss +11 -7
  293. package/src/Message/Message.test.tsx +239 -2
  294. package/src/Message/Message.tsx +133 -241
  295. package/src/Message/MessageAndActions/MessageAndActions.test.tsx +23 -0
  296. package/src/Message/MessageAndActions/MessageAndActions.tsx +22 -0
  297. package/src/Message/MessageAndActions/index.ts +1 -0
  298. package/src/Message/MessageAttachments/MessageAttachmentItem.test.tsx +23 -0
  299. package/src/Message/MessageAttachments/MessageAttachmentItem.tsx +25 -0
  300. package/src/Message/MessageAttachments/MessageAttachmentsContainer.test.tsx +23 -0
  301. package/src/Message/MessageAttachments/MessageAttachmentsContainer.tsx +25 -0
  302. package/src/Message/MessageAttachments/index.ts +2 -0
  303. package/src/Message/MessageInput.tsx +1 -1
  304. package/src/Message/MessageLoading.scss +7 -0
  305. package/src/Message/MessageLoading.test.tsx +23 -0
  306. package/src/Message/MessageLoading.tsx +17 -2
  307. package/src/Message/QuickResponse/QuickResponse.scss +3 -1
  308. package/src/Message/QuickResponse/QuickResponse.test.tsx +131 -0
  309. package/src/Message/QuickResponse/QuickResponse.tsx +3 -2
  310. package/src/Message/QuickResponse/index.ts +1 -0
  311. package/src/Message/QuickStarts/QuickStartTile.tsx +1 -1
  312. package/src/Message/QuickStarts/index.ts +2 -0
  313. package/src/Message/TableMessage/TableMessage.scss +17 -1
  314. package/src/Message/TableMessage/TableMessage.tsx +22 -2
  315. package/src/Message/TextMessage/TextMessage.scss +18 -0
  316. package/src/Message/TextMessage/TextMessage.tsx +39 -3
  317. package/src/Message/UserFeedback/UserFeedback.scss +30 -2
  318. package/src/Message/UserFeedback/UserFeedback.tsx +23 -13
  319. package/src/Message/UserFeedback/UserFeedbackComplete.tsx +1 -4
  320. package/src/Message/UserFeedback/index.ts +2 -0
  321. package/src/Message/index.ts +8 -0
  322. package/src/MessageBar/AttachButton.scss +0 -1
  323. package/src/MessageBar/AttachButton.test.tsx +4 -0
  324. package/src/MessageBar/AttachButton.tsx +4 -1
  325. package/src/MessageBar/MessageBar.scss +66 -6
  326. package/src/MessageBar/MessageBar.test.tsx +129 -1
  327. package/src/MessageBar/MessageBar.tsx +150 -56
  328. package/src/MessageBar/MicrophoneButton.scss +0 -1
  329. package/src/MessageBar/SendButton.scss +0 -1
  330. package/src/MessageBar/StopButton.scss +0 -1
  331. package/src/Onboarding/Onboarding.scss +101 -0
  332. package/src/Onboarding/Onboarding.test.tsx +148 -0
  333. package/src/Onboarding/Onboarding.tsx +126 -0
  334. package/src/Onboarding/index.ts +3 -0
  335. package/src/ResponseActions/ResponseActions.scss +12 -1
  336. package/src/ResponseActions/ResponseActions.test.tsx +111 -12
  337. package/src/ResponseActions/ResponseActions.tsx +44 -10
  338. package/src/ResponseActions/ResponseActionsGroups.test.tsx +23 -0
  339. package/src/ResponseActions/ResponseActionsGroups.tsx +28 -0
  340. package/src/ResponseActions/index.ts +1 -0
  341. package/src/ToolCall/ToolCall.scss +1 -1
  342. package/src/ToolCall/ToolCall.test.tsx +91 -0
  343. package/src/ToolCall/ToolCall.tsx +49 -4
  344. package/src/ToolResponse/ToolResponse.scss +13 -3
  345. package/src/ToolResponse/ToolResponse.test.tsx +119 -0
  346. package/src/ToolResponse/ToolResponse.tsx +82 -7
  347. package/src/__mocks__/monaco-editor.ts +19 -0
  348. package/src/index.ts +6 -0
  349. package/src/main.scss +2 -0
  350. package/tsconfig.json +1 -1
  351. package/patternfly-docs/content/extensions/chatbot/about-chatbot.md +0 -44
@@ -592,6 +592,101 @@ describe('ChatbotConversationHistoryNav', () => {
592
592
  expect(screen.getByRole('dialog', { name: /Chat history I am a sample search/i })).toBeInTheDocument();
593
593
  });
594
594
 
595
+ it('Does not render search actions by default', () => {
596
+ const handleSearch = jest.fn();
597
+ const groupedConversations: { [key: string]: Conversation[] } = {
598
+ Today: [...initialConversations, { id: '2', text: 'Chatbot extension' }]
599
+ };
600
+
601
+ render(
602
+ <ChatbotConversationHistoryNav
603
+ onDrawerToggle={onDrawerToggle}
604
+ isDrawerOpen={true}
605
+ displayMode={ChatbotDisplayMode.fullscreen}
606
+ setIsDrawerOpen={jest.fn()}
607
+ reverseButtonOrder={false}
608
+ conversations={groupedConversations}
609
+ handleTextInputChange={handleSearch}
610
+ />
611
+ );
612
+
613
+ const searchInput = screen.getByPlaceholderText(/Search/i);
614
+
615
+ expect(searchInput.parentElement?.previousElementSibling).toBeNull();
616
+ expect(searchInput.parentElement?.nextElementSibling).toBeNull();
617
+ });
618
+
619
+ it('Renders with action at start when searchActionStart is passed', () => {
620
+ const handleSearch = jest.fn();
621
+ const groupedConversations: { [key: string]: Conversation[] } = {
622
+ Today: [...initialConversations, { id: '2', text: 'Chatbot extension' }]
623
+ };
624
+
625
+ render(
626
+ <ChatbotConversationHistoryNav
627
+ onDrawerToggle={onDrawerToggle}
628
+ isDrawerOpen={true}
629
+ displayMode={ChatbotDisplayMode.fullscreen}
630
+ setIsDrawerOpen={jest.fn()}
631
+ reverseButtonOrder={false}
632
+ conversations={groupedConversations}
633
+ handleTextInputChange={handleSearch}
634
+ searchActionStart={<div>Search action start test</div>}
635
+ />
636
+ );
637
+
638
+ expect(screen.getByText('Search action start test')).toBeVisible();
639
+ });
640
+
641
+ it('Renders with action at end when searchActionEnd is passed', () => {
642
+ const handleSearch = jest.fn();
643
+ const groupedConversations: { [key: string]: Conversation[] } = {
644
+ Today: [...initialConversations, { id: '2', text: 'Chatbot extension' }]
645
+ };
646
+
647
+ render(
648
+ <ChatbotConversationHistoryNav
649
+ onDrawerToggle={onDrawerToggle}
650
+ isDrawerOpen={true}
651
+ displayMode={ChatbotDisplayMode.fullscreen}
652
+ setIsDrawerOpen={jest.fn()}
653
+ reverseButtonOrder={false}
654
+ handleTextInputChange={handleSearch}
655
+ conversations={groupedConversations}
656
+ searchActionEnd={<div>Search action end test</div>}
657
+ />
658
+ );
659
+
660
+ expect(screen.getByText('Search action end test')).toBeVisible();
661
+ });
662
+
663
+ it('Overrides default search input and actions when searchToolbar is passed', () => {
664
+ const handleSearch = jest.fn();
665
+ const groupedConversations: { [key: string]: Conversation[] } = {
666
+ Today: [...initialConversations, { id: '2', text: 'Chatbot extension' }]
667
+ };
668
+
669
+ render(
670
+ <ChatbotConversationHistoryNav
671
+ onDrawerToggle={onDrawerToggle}
672
+ isDrawerOpen={true}
673
+ displayMode={ChatbotDisplayMode.fullscreen}
674
+ setIsDrawerOpen={jest.fn()}
675
+ reverseButtonOrder={false}
676
+ conversations={groupedConversations}
677
+ handleTextInputChange={handleSearch}
678
+ searchActionStart={<div>Search action start test</div>}
679
+ searchActionEnd={<div>Search action end test</div>}
680
+ searchToolbar={<div>Custom toolbar</div>}
681
+ />
682
+ );
683
+
684
+ expect(screen.queryByPlaceholderText(/Search/i)).not.toBeInTheDocument();
685
+ expect(screen.queryByText('Search action start test')).not.toBeInTheDocument();
686
+ expect(screen.queryByText('Search action end test')).not.toBeInTheDocument();
687
+ expect(screen.getByText('Custom toolbar')).toBeInTheDocument();
688
+ });
689
+
595
690
  it('overrides nav title heading level when navTitleProps.headingLevel is passed', () => {
596
691
  render(
597
692
  <ChatbotConversationHistoryNav
@@ -8,6 +8,7 @@ import { useRef, Fragment } from 'react';
8
8
  import {
9
9
  Button,
10
10
  ButtonProps,
11
+ Divider,
11
12
  Drawer,
12
13
  DrawerPanelContent,
13
14
  DrawerContent,
@@ -17,6 +18,8 @@ import {
17
18
  DrawerActions,
18
19
  DrawerCloseButton,
19
20
  DrawerContentBody,
21
+ InputGroup,
22
+ InputGroupItem,
20
23
  SearchInput,
21
24
  Title,
22
25
  DrawerPanelContentProps,
@@ -28,10 +31,10 @@ import {
28
31
  DrawerPanelBodyProps,
29
32
  SkeletonProps,
30
33
  Icon,
31
- MenuProps,
32
34
  TitleProps,
33
- MenuListProps,
34
35
  SearchInputProps,
36
+ MenuProps,
37
+ MenuListProps,
35
38
  MenuList,
36
39
  MenuGroup,
37
40
  MenuItem,
@@ -125,6 +128,8 @@ export interface ChatbotConversationHistoryNavProps extends DrawerProps {
125
128
  drawerCloseButtonProps?: DrawerCloseButtonProps;
126
129
  /** Additional props appleid to drawer panel body */
127
130
  drawerPanelBodyProps?: DrawerPanelBodyProps;
131
+ /** Flag indicating whether a divider should render between the drawer head and title. */
132
+ hasDrawerHeadDivider?: boolean;
128
133
  /** Whether to show drawer loading state */
129
134
  isLoading?: boolean;
130
135
  /** Additional props for loading state */
@@ -145,6 +150,12 @@ export interface ChatbotConversationHistoryNavProps extends DrawerProps {
145
150
  navTitleProps?: Partial<TitleProps>;
146
151
  /** Visually hidden text that gets announced by assistive technologies. Should be used to convey the result count when the search input value changes. */
147
152
  searchInputScreenReaderText?: string;
153
+ /** Custom action rendered before the search input. */
154
+ searchActionStart?: React.ReactNode;
155
+ /** Custom action rendered after the search input. */
156
+ searchActionEnd?: React.ReactNode;
157
+ /** A custom search toolbar to render below the title. This will override the default search actions and/or search input. */
158
+ searchToolbar?: React.ReactNode;
148
159
  /** Additional props passed to MenuContent */
149
160
  menuContentProps?: Omit<MenuContentProps, 'ref'>;
150
161
  }
@@ -175,6 +186,7 @@ export const ChatbotConversationHistoryNav: FunctionComponent<ChatbotConversatio
175
186
  drawerActionsProps,
176
187
  drawerCloseButtonProps,
177
188
  drawerPanelBodyProps,
189
+ hasDrawerHeadDivider,
178
190
  isLoading,
179
191
  loadingState,
180
192
  errorState,
@@ -185,6 +197,9 @@ export const ChatbotConversationHistoryNav: FunctionComponent<ChatbotConversatio
185
197
  navTitleProps,
186
198
  navTitleIcon = <OutlinedClockIcon />,
187
199
  searchInputScreenReaderText,
200
+ searchActionStart,
201
+ searchActionEnd,
202
+ searchToolbar,
188
203
  menuProps,
189
204
  menuGroupProps,
190
205
  menuContentProps,
@@ -287,6 +302,38 @@ export const ChatbotConversationHistoryNav: FunctionComponent<ChatbotConversatio
287
302
  </>
288
303
  );
289
304
 
305
+ const searchInputContainer = handleTextInputChange && (
306
+ <div className="pf-chatbot__input">
307
+ <SearchInput
308
+ aria-label={searchInputAriaLabel}
309
+ onChange={(_event, value) => handleTextInputChange(value)}
310
+ placeholder={searchInputPlaceholder}
311
+ {...searchInputProps}
312
+ />
313
+ {searchInputScreenReaderText && (
314
+ <div className="pf-chatbot__filter-announcement pf-chatbot-m-hidden">{searchInputScreenReaderText}</div>
315
+ )}
316
+ </div>
317
+ );
318
+
319
+ const renderSearchAndActions = () => {
320
+ if (searchToolbar) {
321
+ return searchToolbar;
322
+ }
323
+
324
+ return searchActionStart || searchActionEnd ? (
325
+ <div className="pf-chatbot__history-search-actions">
326
+ <InputGroup>
327
+ {searchActionStart && <InputGroupItem>{searchActionStart}</InputGroupItem>}
328
+ {searchInputContainer && <InputGroupItem isFill>{searchInputContainer}</InputGroupItem>}
329
+ {searchActionEnd && <InputGroupItem>{searchActionEnd}</InputGroupItem>}
330
+ </InputGroup>
331
+ </div>
332
+ ) : (
333
+ searchInputContainer
334
+ );
335
+ };
336
+
290
337
  const renderPanelContent = () => {
291
338
  const drawer = (
292
339
  <>
@@ -309,6 +356,7 @@ export const ChatbotConversationHistoryNav: FunctionComponent<ChatbotConversatio
309
356
  )}
310
357
  </DrawerActions>
311
358
  </DrawerHead>
359
+ {hasDrawerHeadDivider && <Divider className="pf-chatbot__heading-divider" />}
312
360
  <div className="pf-chatbot__heading-container">
313
361
  <div className="pf-chatbot__title-container">
314
362
  <Icon size="lg" className="pf-chatbot__title-icon">
@@ -318,19 +366,7 @@ export const ChatbotConversationHistoryNav: FunctionComponent<ChatbotConversatio
318
366
  {title}
319
367
  </Title>
320
368
  </div>
321
- {!isLoading && handleTextInputChange && (
322
- <div className="pf-chatbot__input">
323
- <SearchInput
324
- aria-label={searchInputAriaLabel}
325
- onChange={(_event, value) => handleTextInputChange(value)}
326
- placeholder={searchInputPlaceholder}
327
- {...searchInputProps}
328
- />
329
- {searchInputScreenReaderText && (
330
- <div className="pf-chatbot__filter-announcement pf-chatbot-m-hidden">{searchInputScreenReaderText}</div>
331
- )}
332
- </div>
333
- )}
369
+ {!isLoading && renderSearchAndActions()}
334
370
  </div>
335
371
  {isLoading ? <LoadingState {...loadingState} /> : renderDrawerContent()}
336
372
  </>
@@ -11,6 +11,10 @@
11
11
  flex-direction: column;
12
12
  row-gap: var(--pf-chatbot__footer--RowGap);
13
13
  position: relative; // this is so focus ring on parent chatbot doesn't include footer
14
+
15
+ &.pf-m-primary {
16
+ background-color: var(--pf-t--global--background--color--primary--default);
17
+ }
14
18
  }
15
19
  .pf-chatbot__footer-container {
16
20
  padding: 0 var(--pf-t--global--spacer--lg) var(--pf-t--global--spacer--lg) var(--pf-t--global--spacer--lg);
@@ -62,3 +66,20 @@
62
66
  padding: 0 var(--pf-t--global--spacer--sm) var(--pf-t--global--spacer--sm) var(--pf-t--global--spacer--sm);
63
67
  row-gap: var(--pf-t--global--spacer--sm);
64
68
  }
69
+
70
+ // ============================================================================
71
+ // High contrast
72
+ // ============================================================================
73
+ :root:where(.pf-v6-theme-high-contrast) {
74
+ // Chatbot Display Mode - Fullscreen and Embedded
75
+ @media screen and (min-width: 64rem) {
76
+ .pf-chatbot--embedded,
77
+ .pf-chatbot--fullscreen {
78
+ .pf-chatbot__footer {
79
+ .pf-v6-c-divider {
80
+ display: var(--pf-v6-hidden-visible--Display);
81
+ }
82
+ }
83
+ }
84
+ }
85
+ }
@@ -15,10 +15,19 @@ describe('ChatbotFooter', () => {
15
15
 
16
16
  it('should handle isCompact', () => {
17
17
  render(
18
- <ChatbotFooter className="custom-class" isCompact data-testid="footer">
18
+ <ChatbotFooter isCompact data-testid="footer">
19
19
  Chatbot Content
20
20
  </ChatbotFooter>
21
21
  );
22
22
  expect(screen.getByTestId('footer')).toHaveClass('pf-m-compact');
23
23
  });
24
+
25
+ it('should handle isPrimary', () => {
26
+ render(
27
+ <ChatbotFooter isPrimary data-testid="footer">
28
+ Chatbot Content
29
+ </ChatbotFooter>
30
+ );
31
+ expect(screen.getByTestId('footer')).toHaveClass('pf-m-primary');
32
+ });
24
33
  });
@@ -13,20 +13,27 @@ import type { HTMLProps, FunctionComponent } from 'react';
13
13
  import { Divider } from '@patternfly/react-core';
14
14
 
15
15
  export interface ChatbotFooterProps extends HTMLProps<HTMLDivElement> {
16
- /** Children for the Footer that supports MessageBar and FootNote components*/
16
+ /** Children for the footer - supports MessageBar and FootNote components*/
17
17
  children?: React.ReactNode;
18
- /** Custom classname for the Footer component */
18
+ /** Custom classname for the footer component */
19
19
  className?: string;
20
+ /** Sets footer to compact styling. */
20
21
  isCompact?: boolean;
22
+ /** Sets background color to primary */
23
+ isPrimary?: boolean;
21
24
  }
22
25
 
23
26
  export const ChatbotFooter: FunctionComponent<ChatbotFooterProps> = ({
24
27
  children,
25
28
  className,
26
29
  isCompact,
30
+ isPrimary,
27
31
  ...props
28
32
  }: ChatbotFooterProps) => (
29
- <div className={`pf-chatbot__footer ${isCompact ? 'pf-m-compact' : ''} ${className ?? ''}`} {...props}>
33
+ <div
34
+ className={`pf-chatbot__footer ${isCompact ? 'pf-m-compact' : ''} ${isPrimary ? 'pf-m-primary' : ''} ${className ?? ''}`}
35
+ {...props}
36
+ >
30
37
  <Divider />
31
38
  <div className="pf-chatbot__footer-container">{children}</div>
32
39
  </div>
@@ -91,6 +91,10 @@
91
91
  align-items: center;
92
92
  justify-content: center;
93
93
 
94
+ &::before {
95
+ border-radius: inherit;
96
+ }
97
+
94
98
  .pf-v6-c-button__icon,
95
99
  .pf-v6-c-menu-toggle__icon,
96
100
  .pf-v6-c-icon__content {
@@ -162,3 +166,18 @@
162
166
  .pf-chatbot__header .pf-chatbot__actions .pf-v6-c-menu-toggle.pf-m-secondary.pf-m-compact {
163
167
  width: initial;
164
168
  }
169
+
170
+ // ============================================================================
171
+ // High contrast
172
+ // ============================================================================
173
+ :root:where(.pf-v6-theme-high-contrast) {
174
+ // Chatbot Display Mode - Fullscreen and Embedded
175
+ @media screen and (min-width: 64rem) {
176
+ .pf-chatbot--fullscreen,
177
+ .pf-chatbot--embedded {
178
+ .pf-chatbot__header__divider {
179
+ display: var(--pf-v6-hidden-visible--Display);
180
+ }
181
+ }
182
+ }
183
+ }
@@ -1,5 +1,5 @@
1
1
  import type { Ref, FunctionComponent } from 'react';
2
- import { forwardRef } from 'react';
2
+ import { forwardRef, useEffect, useMemo, useRef, useState } from 'react';
3
3
 
4
4
  import { Button, ButtonProps, Icon, Tooltip, TooltipProps } from '@patternfly/react-core';
5
5
  import BarsIcon from '@patternfly/react-icons/dist/esm/icons/bars-icon';
@@ -30,21 +30,43 @@ const ChatbotHeaderMenuBase: FunctionComponent<ChatbotHeaderMenuProps> = ({
30
30
  tooltipContent = 'Chat history menu',
31
31
  isCompact,
32
32
  ...props
33
- }: ChatbotHeaderMenuProps) => (
34
- <div className={`pf-chatbot__menu ${className}`}>
35
- <Tooltip
36
- content={tooltipContent}
37
- position="bottom"
38
- // prevents VO announcements of both aria label and tooltip
39
- aria="none"
40
- {...tooltipProps}
41
- >
33
+ }: ChatbotHeaderMenuProps) => {
34
+ const [isDrawerAnimating, setIsDrawerAnimating] = useState(false);
35
+ // I'd like to use a prop here later if this works
36
+ const drawerState = props['aria-expanded'];
37
+ const isDrawerOpen = drawerState === true;
38
+ const prevDrawerStateRef = useRef<boolean | undefined>(isDrawerOpen);
39
+ const buttonRef = useRef<HTMLButtonElement | null>(null);
40
+
41
+ useEffect(() => {
42
+ if (drawerState !== undefined) {
43
+ const wasDrawerOpen = prevDrawerStateRef.current === true;
44
+ const isDrawerClosing = wasDrawerOpen && !isDrawerOpen;
45
+
46
+ setIsDrawerAnimating(true);
47
+ const timeout = setTimeout(() => {
48
+ setIsDrawerAnimating(false);
49
+
50
+ if (isDrawerClosing) {
51
+ requestAnimationFrame(() => {
52
+ buttonRef.current?.focus();
53
+ });
54
+ }
55
+ }, 350);
56
+
57
+ prevDrawerStateRef.current = isDrawerOpen;
58
+ return () => clearTimeout(timeout);
59
+ }
60
+ }, [drawerState, isDrawerOpen]);
61
+
62
+ const button = useMemo(
63
+ () => (
42
64
  <Button
43
65
  className={`pf-chatbot__button--toggle-menu ${isCompact ? 'pf-m-compact' : ''}`}
44
66
  variant="plain"
45
67
  onClick={onMenuToggle}
46
68
  aria-label={menuAriaLabel}
47
- ref={innerRef}
69
+ ref={innerRef ?? buttonRef}
48
70
  icon={
49
71
  <Icon size={isCompact ? 'lg' : 'xl'} isInline>
50
72
  <BarsIcon />
@@ -53,9 +75,29 @@ const ChatbotHeaderMenuBase: FunctionComponent<ChatbotHeaderMenuProps> = ({
53
75
  size={isCompact ? 'sm' : undefined}
54
76
  {...props}
55
77
  />
56
- </Tooltip>
57
- </div>
58
- );
78
+ ),
79
+ // eslint-disable-next-line react-hooks/exhaustive-deps
80
+ [isCompact, menuAriaLabel, onMenuToggle, innerRef, buttonRef]
81
+ );
82
+
83
+ return (
84
+ <div className={`pf-chatbot__menu ${className}`}>
85
+ {isDrawerAnimating ? (
86
+ button
87
+ ) : (
88
+ <Tooltip
89
+ content={tooltipContent}
90
+ position="bottom"
91
+ // prevents VO announcements of both aria label and tooltip
92
+ aria="none"
93
+ {...tooltipProps}
94
+ >
95
+ {button}
96
+ </Tooltip>
97
+ )}
98
+ </div>
99
+ );
100
+ };
59
101
 
60
102
  export const ChatbotHeaderMenu = forwardRef((props: ChatbotHeaderMenuProps, ref: Ref<HTMLButtonElement>) => (
61
103
  <ChatbotHeaderMenuBase innerRef={ref} {...props} />
@@ -18,7 +18,10 @@
18
18
  .pf-v6-c-modal-box__footer {
19
19
  padding-block-start: var(--pf-t--global--spacer--xl);
20
20
  padding-block-end: var(--pf-t--global--spacer--xl);
21
+ border-top: var(--pf-t--global--border--width--high-contrast--regular) solid
22
+ var(--pf-t--global--border--color--high-contrast);
21
23
  }
24
+
22
25
  .pf-v6-c-modal-box__header {
23
26
  padding-block-end: var(--pf-t--global--spacer--sm);
24
27
  }
@@ -5,16 +5,17 @@
5
5
  import type { FunctionComponent, MouseEvent } from 'react';
6
6
  import { useState, useEffect, useRef } from 'react';
7
7
  import path from 'path-browserify';
8
- import type monaco from 'monaco-editor';
9
8
 
10
9
  // Import PatternFly components
11
10
  import { CodeEditor } from '@patternfly/react-code-editor';
12
11
  import {
12
+ Bullseye,
13
13
  Button,
14
14
  getResizeObserver,
15
15
  ModalBody,
16
16
  ModalFooter,
17
17
  ModalHeader,
18
+ Spinner,
18
19
  Stack,
19
20
  StackItem
20
21
  } from '@patternfly/react-core';
@@ -22,6 +23,17 @@ import FileDetails, { extensionToLanguage } from '../FileDetails';
22
23
  import { ChatbotDisplayMode } from '../Chatbot';
23
24
  import ChatbotModal from '../ChatbotModal/ChatbotModal';
24
25
 
26
+ // Try to lazy load - some consumers need to be below a certain bundle size, but can't use the CDN and don't have webpack
27
+ let monacoInstance: typeof import('monaco-editor') | null = null;
28
+ const loadMonaco = async () => {
29
+ if (!monacoInstance) {
30
+ const [monaco, { loader }] = await Promise.all([import('monaco-editor'), import('@monaco-editor/react')]);
31
+ monacoInstance = monaco;
32
+ loader.config({ monaco });
33
+ }
34
+ return monacoInstance;
35
+ };
36
+
25
37
  export interface CodeModalProps {
26
38
  /** Class applied to code editor */
27
39
  codeEditorControlClassName?: string;
@@ -59,6 +71,8 @@ export interface CodeModalProps {
59
71
  modalBodyClassName?: string;
60
72
  /** Class applied to modal footer */
61
73
  modalFooterClassName?: string;
74
+ /** Aria label applied to spinner when loading Monaco */
75
+ spinnerAriaLabel?: string;
62
76
  }
63
77
 
64
78
  export const CodeModal: FunctionComponent<CodeModalProps> = ({
@@ -80,13 +94,32 @@ export const CodeModal: FunctionComponent<CodeModalProps> = ({
80
94
  modalHeaderClassName,
81
95
  modalBodyClassName,
82
96
  modalFooterClassName,
97
+ spinnerAriaLabel = 'Loading',
83
98
  ...props
84
99
  }: CodeModalProps) => {
85
100
  const [newCode, setNewCode] = useState(code);
86
- const [editorInstance, setEditorInstance] = useState<monaco.editor.IStandaloneCodeEditor | null>(null);
101
+ const [editorInstance, setEditorInstance] = useState<any>(null);
87
102
  const [isEditorReady, setIsEditorReady] = useState(false);
103
+ const [isMonacoLoading, setIsMonacoLoading] = useState(false);
104
+ const [isMonacoLoaded, setIsMonacoLoaded] = useState(false);
88
105
  const containerRef = useRef<HTMLDivElement>(null);
89
106
 
107
+ useEffect(() => {
108
+ if (isModalOpen && !isMonacoLoaded && !isMonacoLoading) {
109
+ setIsMonacoLoading(true);
110
+ loadMonaco()
111
+ .then(() => {
112
+ setIsMonacoLoaded(true);
113
+ setIsMonacoLoading(false);
114
+ })
115
+ .catch((error) => {
116
+ // eslint-disable-next-line no-console
117
+ console.error('Failed to load Monaco editor:', error);
118
+ setIsMonacoLoading(false);
119
+ });
120
+ }
121
+ }, [isModalOpen, isMonacoLoaded, isMonacoLoading]);
122
+
90
123
  useEffect(() => {
91
124
  if (!isModalOpen || !isEditorReady || !editorInstance || !containerRef.current) {
92
125
  return;
@@ -144,6 +177,42 @@ export const CodeModal: FunctionComponent<CodeModalProps> = ({
144
177
  }
145
178
  };
146
179
 
180
+ const renderMonacoEditor = () => {
181
+ if (isMonacoLoading) {
182
+ return (
183
+ <Bullseye>
184
+ <Spinner aria-label={spinnerAriaLabel} />
185
+ </Bullseye>
186
+ );
187
+ }
188
+ if (isMonacoLoaded) {
189
+ return (
190
+ <CodeEditor
191
+ isDarkTheme
192
+ isLineNumbersVisible={isLineNumbersVisible}
193
+ isLanguageLabelVisible
194
+ isCopyEnabled={isCopyEnabled}
195
+ isReadOnly={isReadOnly}
196
+ code={newCode}
197
+ language={extensionToLanguage[path.extname(fileName).slice(1)]}
198
+ onEditorDidMount={onEditorDidMount}
199
+ onCodeChange={onCodeChange}
200
+ className={codeEditorClassName}
201
+ isFullHeight
202
+ options={{
203
+ glyphMargin: false,
204
+ folding: false,
205
+ // prevents Monaco from handling resizing itself
206
+ // was causing ResizeObserver issues
207
+ automaticLayout: false
208
+ }}
209
+ {...props}
210
+ />
211
+ );
212
+ }
213
+ return null;
214
+ };
215
+
147
216
  const modal = (
148
217
  <ChatbotModal
149
218
  isOpen={isModalOpen}
@@ -162,27 +231,7 @@ export const CodeModal: FunctionComponent<CodeModalProps> = ({
162
231
  <FileDetails fileName={fileName} />
163
232
  </StackItem>
164
233
  <div className="pf-v6-l-stack__item pf-chatbot__code-modal-editor" ref={containerRef}>
165
- <CodeEditor
166
- isDarkTheme
167
- isLineNumbersVisible={isLineNumbersVisible}
168
- isLanguageLabelVisible
169
- isCopyEnabled={isCopyEnabled}
170
- isReadOnly={isReadOnly}
171
- code={newCode}
172
- language={extensionToLanguage[path.extname(fileName).slice(1)]}
173
- onEditorDidMount={onEditorDidMount}
174
- onCodeChange={onCodeChange}
175
- className={codeEditorClassName}
176
- isFullHeight
177
- options={{
178
- glyphMargin: false,
179
- folding: false,
180
- // prevents Monaco from handling resizing itself
181
- // was causing ResizeObserver issues
182
- automaticLayout: false
183
- }}
184
- {...props}
185
- />
234
+ {renderMonacoEditor()}
186
235
  </div>
187
236
  </Stack>
188
237
  </ModalBody>
@@ -1,5 +1,5 @@
1
1
  .pf-chatbot__deep-thinking {
2
- --pf-v6-c-card--BorderColor: var(--pf-t--global--border--color--control--read-only);
2
+ --pf-v6-c-card--BorderColor: var(--pf-t--global--border--color--default);
3
3
  overflow: unset;
4
4
  }
5
5