@patternfly/chatbot 6.5.0-prerelease.9 → 6.5.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 (314) hide show
  1. package/dist/cjs/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.d.ts +9 -1
  2. package/dist/cjs/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.js +9 -2
  3. package/dist/cjs/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.test.js +38 -0
  4. package/dist/cjs/ChatbotHeader/ChatbotHeaderMenu.js +29 -2
  5. package/dist/cjs/CodeModal/CodeModal.d.ts +2 -0
  6. package/dist/cjs/CodeModal/CodeModal.js +53 -12
  7. package/dist/cjs/DeepThinking/DeepThinking.d.ts +13 -0
  8. package/dist/cjs/DeepThinking/DeepThinking.js +31 -3
  9. package/dist/cjs/DeepThinking/DeepThinking.test.js +80 -0
  10. package/dist/cjs/MarkdownContent/MarkdownContent.d.ts +44 -0
  11. package/dist/cjs/MarkdownContent/MarkdownContent.js +181 -0
  12. package/dist/cjs/MarkdownContent/MarkdownContent.test.d.ts +1 -0
  13. package/dist/cjs/MarkdownContent/MarkdownContent.test.js +192 -0
  14. package/dist/cjs/MarkdownContent/index.d.ts +2 -0
  15. package/dist/cjs/MarkdownContent/index.js +23 -0
  16. package/dist/cjs/Message/CodeBlockMessage/CodeBlockMessage.d.ts +3 -1
  17. package/dist/cjs/Message/CodeBlockMessage/CodeBlockMessage.js +15 -4
  18. package/dist/cjs/Message/CodeBlockMessage/CodeBlockMessage.test.d.ts +1 -0
  19. package/dist/cjs/Message/CodeBlockMessage/CodeBlockMessage.test.js +131 -0
  20. package/dist/cjs/Message/ErrorMessage/ErrorMessage.d.ts +15 -1
  21. package/dist/cjs/Message/ErrorMessage/ErrorMessage.js +5 -3
  22. package/dist/cjs/Message/ErrorMessage/ErrorMessage.test.d.ts +1 -0
  23. package/dist/cjs/Message/ErrorMessage/ErrorMessage.test.js +30 -0
  24. package/dist/cjs/Message/LinkMessage/LinkMessage.d.ts +5 -1
  25. package/dist/cjs/Message/LinkMessage/LinkMessage.js +4 -3
  26. package/dist/cjs/Message/ListMessage/OrderedListMessage.d.ts +9 -1
  27. package/dist/cjs/Message/ListMessage/OrderedListMessage.js +2 -1
  28. package/dist/cjs/Message/ListMessage/UnorderedListMessage.d.ts +7 -1
  29. package/dist/cjs/Message/ListMessage/UnorderedListMessage.js +2 -1
  30. package/dist/cjs/Message/Message.d.ts +20 -3
  31. package/dist/cjs/Message/Message.js +7 -160
  32. package/dist/cjs/Message/Message.test.js +129 -2
  33. package/dist/cjs/Message/MessageAndActions/MessageAndActions.d.ts +14 -0
  34. package/dist/cjs/Message/MessageAndActions/MessageAndActions.js +22 -0
  35. package/dist/cjs/Message/MessageAndActions/MessageAndActions.test.d.ts +1 -0
  36. package/dist/cjs/Message/MessageAndActions/MessageAndActions.test.js +25 -0
  37. package/dist/cjs/Message/MessageAndActions/index.d.ts +1 -0
  38. package/dist/cjs/Message/MessageAndActions/index.js +17 -0
  39. package/dist/cjs/Message/MessageAttachments/MessageAttachmentItem.d.ts +13 -0
  40. package/dist/cjs/Message/MessageAttachments/MessageAttachmentItem.js +22 -0
  41. package/dist/cjs/Message/MessageAttachments/MessageAttachmentItem.test.d.ts +1 -0
  42. package/dist/cjs/Message/MessageAttachments/MessageAttachmentItem.test.js +25 -0
  43. package/dist/cjs/Message/MessageAttachments/MessageAttachmentsContainer.d.ts +13 -0
  44. package/dist/cjs/Message/MessageAttachments/MessageAttachmentsContainer.js +22 -0
  45. package/dist/cjs/Message/MessageAttachments/MessageAttachmentsContainer.test.d.ts +1 -0
  46. package/dist/cjs/Message/MessageAttachments/MessageAttachmentsContainer.test.js +25 -0
  47. package/dist/cjs/Message/MessageAttachments/index.d.ts +2 -0
  48. package/dist/cjs/Message/MessageAttachments/index.js +18 -0
  49. package/dist/cjs/Message/MessageInput.d.ts +1 -1
  50. package/dist/cjs/Message/MessageInput.js +3 -1
  51. package/dist/cjs/Message/MessageLoading.d.ts +13 -4
  52. package/dist/cjs/Message/MessageLoading.js +19 -5
  53. package/dist/cjs/Message/MessageLoading.test.d.ts +1 -0
  54. package/dist/cjs/Message/MessageLoading.test.js +25 -0
  55. package/dist/cjs/Message/QuickResponse/QuickResponse.js +3 -2
  56. package/dist/cjs/Message/QuickResponse/QuickResponse.test.d.ts +1 -0
  57. package/dist/cjs/Message/QuickResponse/QuickResponse.test.js +109 -0
  58. package/dist/cjs/Message/QuickResponse/index.d.ts +1 -0
  59. package/dist/cjs/Message/QuickResponse/index.js +17 -0
  60. package/dist/cjs/Message/QuickStarts/QuickStartTile.d.ts +1 -1
  61. package/dist/cjs/Message/QuickStarts/QuickStartTile.js +3 -2
  62. package/dist/cjs/Message/QuickStarts/index.d.ts +2 -0
  63. package/dist/cjs/Message/QuickStarts/index.js +18 -0
  64. package/dist/cjs/Message/TableMessage/TableMessage.d.ts +6 -1
  65. package/dist/cjs/Message/TableMessage/TableMessage.js +3 -2
  66. package/dist/cjs/Message/TextMessage/TextMessage.d.ts +8 -1
  67. package/dist/cjs/Message/TextMessage/TextMessage.js +3 -2
  68. package/dist/cjs/Message/UserFeedback/UserFeedback.d.ts +3 -1
  69. package/dist/cjs/Message/UserFeedback/UserFeedback.js +8 -6
  70. package/dist/cjs/Message/UserFeedback/UserFeedbackComplete.d.ts +1 -1
  71. package/dist/cjs/Message/UserFeedback/UserFeedbackComplete.js +3 -2
  72. package/dist/cjs/Message/UserFeedback/index.d.ts +2 -0
  73. package/dist/cjs/Message/UserFeedback/index.js +18 -0
  74. package/dist/cjs/Message/index.d.ts +8 -0
  75. package/dist/cjs/Message/index.js +8 -0
  76. package/dist/cjs/MessageBar/MessageBar.d.ts +4 -0
  77. package/dist/cjs/MessageBar/MessageBar.js +20 -5
  78. package/dist/cjs/MessageBar/MessageBar.test.js +8 -0
  79. package/dist/cjs/Onboarding/Onboarding.d.ts +36 -0
  80. package/dist/cjs/Onboarding/Onboarding.js +37 -0
  81. package/dist/cjs/Onboarding/Onboarding.test.d.ts +1 -0
  82. package/dist/cjs/Onboarding/Onboarding.test.js +80 -0
  83. package/dist/cjs/Onboarding/index.d.ts +2 -0
  84. package/dist/cjs/Onboarding/index.js +23 -0
  85. package/dist/cjs/ResponseActions/ResponseActions.d.ts +7 -0
  86. package/dist/cjs/ResponseActions/ResponseActions.js +28 -7
  87. package/dist/cjs/ResponseActions/ResponseActions.test.js +67 -12
  88. package/dist/cjs/ResponseActions/ResponseActionsGroups.d.ts +13 -0
  89. package/dist/cjs/ResponseActions/ResponseActionsGroups.js +22 -0
  90. package/dist/cjs/ResponseActions/ResponseActionsGroups.test.d.ts +1 -0
  91. package/dist/cjs/ResponseActions/ResponseActionsGroups.test.js +25 -0
  92. package/dist/cjs/ResponseActions/index.d.ts +1 -0
  93. package/dist/cjs/ResponseActions/index.js +1 -0
  94. package/dist/cjs/ToolCall/ToolCall.d.ts +11 -0
  95. package/dist/cjs/ToolCall/ToolCall.js +24 -3
  96. package/dist/cjs/ToolCall/ToolCall.test.js +57 -0
  97. package/dist/cjs/ToolResponse/ToolResponse.d.ts +17 -0
  98. package/dist/cjs/ToolResponse/ToolResponse.js +49 -3
  99. package/dist/cjs/ToolResponse/ToolResponse.test.js +100 -0
  100. package/dist/cjs/index.d.ts +4 -0
  101. package/dist/cjs/index.js +7 -1
  102. package/dist/css/main.css +264 -30
  103. package/dist/css/main.css.map +1 -1
  104. package/dist/dynamic/MarkdownContent/package.json +1 -0
  105. package/dist/dynamic/Onboarding/package.json +1 -0
  106. package/dist/esm/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.d.ts +9 -1
  107. package/dist/esm/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.js +10 -3
  108. package/dist/esm/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.test.js +38 -0
  109. package/dist/esm/ChatbotHeader/ChatbotHeaderMenu.js +30 -3
  110. package/dist/esm/CodeModal/CodeModal.d.ts +2 -0
  111. package/dist/esm/CodeModal/CodeModal.js +54 -13
  112. package/dist/esm/DeepThinking/DeepThinking.d.ts +13 -0
  113. package/dist/esm/DeepThinking/DeepThinking.js +28 -3
  114. package/dist/esm/DeepThinking/DeepThinking.test.js +80 -0
  115. package/dist/esm/MarkdownContent/MarkdownContent.d.ts +44 -0
  116. package/dist/esm/MarkdownContent/MarkdownContent.js +174 -0
  117. package/dist/esm/MarkdownContent/MarkdownContent.test.d.ts +1 -0
  118. package/dist/esm/MarkdownContent/MarkdownContent.test.js +187 -0
  119. package/dist/esm/MarkdownContent/index.d.ts +2 -0
  120. package/dist/esm/MarkdownContent/index.js +2 -0
  121. package/dist/esm/Message/CodeBlockMessage/CodeBlockMessage.d.ts +3 -1
  122. package/dist/esm/Message/CodeBlockMessage/CodeBlockMessage.js +15 -4
  123. package/dist/esm/Message/CodeBlockMessage/CodeBlockMessage.test.d.ts +1 -0
  124. package/dist/esm/Message/CodeBlockMessage/CodeBlockMessage.test.js +126 -0
  125. package/dist/esm/Message/ErrorMessage/ErrorMessage.d.ts +15 -1
  126. package/dist/esm/Message/ErrorMessage/ErrorMessage.js +3 -3
  127. package/dist/esm/Message/ErrorMessage/ErrorMessage.test.d.ts +1 -0
  128. package/dist/esm/Message/ErrorMessage/ErrorMessage.test.js +25 -0
  129. package/dist/esm/Message/LinkMessage/LinkMessage.d.ts +5 -1
  130. package/dist/esm/Message/LinkMessage/LinkMessage.js +4 -3
  131. package/dist/esm/Message/ListMessage/OrderedListMessage.d.ts +9 -1
  132. package/dist/esm/Message/ListMessage/OrderedListMessage.js +2 -1
  133. package/dist/esm/Message/ListMessage/UnorderedListMessage.d.ts +7 -1
  134. package/dist/esm/Message/ListMessage/UnorderedListMessage.js +2 -1
  135. package/dist/esm/Message/Message.d.ts +20 -3
  136. package/dist/esm/Message/Message.js +8 -161
  137. package/dist/esm/Message/Message.test.js +129 -2
  138. package/dist/esm/Message/MessageAndActions/MessageAndActions.d.ts +14 -0
  139. package/dist/esm/Message/MessageAndActions/MessageAndActions.js +18 -0
  140. package/dist/esm/Message/MessageAndActions/MessageAndActions.test.d.ts +1 -0
  141. package/dist/esm/Message/MessageAndActions/MessageAndActions.test.js +20 -0
  142. package/dist/esm/Message/MessageAndActions/index.d.ts +1 -0
  143. package/dist/esm/Message/MessageAndActions/index.js +1 -0
  144. package/dist/esm/Message/MessageAttachments/MessageAttachmentItem.d.ts +13 -0
  145. package/dist/esm/Message/MessageAttachments/MessageAttachmentItem.js +18 -0
  146. package/dist/esm/Message/MessageAttachments/MessageAttachmentItem.test.d.ts +1 -0
  147. package/dist/esm/Message/MessageAttachments/MessageAttachmentItem.test.js +20 -0
  148. package/dist/esm/Message/MessageAttachments/MessageAttachmentsContainer.d.ts +13 -0
  149. package/dist/esm/Message/MessageAttachments/MessageAttachmentsContainer.js +18 -0
  150. package/dist/esm/Message/MessageAttachments/MessageAttachmentsContainer.test.d.ts +1 -0
  151. package/dist/esm/Message/MessageAttachments/MessageAttachmentsContainer.test.js +20 -0
  152. package/dist/esm/Message/MessageAttachments/index.d.ts +2 -0
  153. package/dist/esm/Message/MessageAttachments/index.js +2 -0
  154. package/dist/esm/Message/MessageInput.d.ts +1 -1
  155. package/dist/esm/Message/MessageInput.js +1 -1
  156. package/dist/esm/Message/MessageLoading.d.ts +13 -4
  157. package/dist/esm/Message/MessageLoading.js +16 -4
  158. package/dist/esm/Message/MessageLoading.test.d.ts +1 -0
  159. package/dist/esm/Message/MessageLoading.test.js +20 -0
  160. package/dist/esm/Message/QuickResponse/QuickResponse.js +3 -2
  161. package/dist/esm/Message/QuickResponse/QuickResponse.test.d.ts +1 -0
  162. package/dist/esm/Message/QuickResponse/QuickResponse.test.js +104 -0
  163. package/dist/esm/Message/QuickResponse/index.d.ts +1 -0
  164. package/dist/esm/Message/QuickResponse/index.js +1 -0
  165. package/dist/esm/Message/QuickStarts/QuickStartTile.d.ts +1 -1
  166. package/dist/esm/Message/QuickStarts/QuickStartTile.js +1 -1
  167. package/dist/esm/Message/QuickStarts/index.d.ts +2 -0
  168. package/dist/esm/Message/QuickStarts/index.js +2 -0
  169. package/dist/esm/Message/TableMessage/TableMessage.d.ts +6 -1
  170. package/dist/esm/Message/TableMessage/TableMessage.js +3 -2
  171. package/dist/esm/Message/TextMessage/TextMessage.d.ts +8 -1
  172. package/dist/esm/Message/TextMessage/TextMessage.js +3 -2
  173. package/dist/esm/Message/UserFeedback/UserFeedback.d.ts +3 -1
  174. package/dist/esm/Message/UserFeedback/UserFeedback.js +7 -7
  175. package/dist/esm/Message/UserFeedback/UserFeedbackComplete.d.ts +1 -1
  176. package/dist/esm/Message/UserFeedback/UserFeedbackComplete.js +1 -2
  177. package/dist/esm/Message/UserFeedback/index.d.ts +2 -0
  178. package/dist/esm/Message/UserFeedback/index.js +2 -0
  179. package/dist/esm/Message/index.d.ts +8 -0
  180. package/dist/esm/Message/index.js +8 -0
  181. package/dist/esm/MessageBar/MessageBar.d.ts +4 -0
  182. package/dist/esm/MessageBar/MessageBar.js +20 -5
  183. package/dist/esm/MessageBar/MessageBar.test.js +8 -0
  184. package/dist/esm/Onboarding/Onboarding.d.ts +36 -0
  185. package/dist/esm/Onboarding/Onboarding.js +30 -0
  186. package/dist/esm/Onboarding/Onboarding.test.d.ts +1 -0
  187. package/dist/esm/Onboarding/Onboarding.test.js +75 -0
  188. package/dist/esm/Onboarding/index.d.ts +2 -0
  189. package/dist/esm/Onboarding/index.js +2 -0
  190. package/dist/esm/ResponseActions/ResponseActions.d.ts +7 -0
  191. package/dist/esm/ResponseActions/ResponseActions.js +28 -7
  192. package/dist/esm/ResponseActions/ResponseActions.test.js +67 -12
  193. package/dist/esm/ResponseActions/ResponseActionsGroups.d.ts +13 -0
  194. package/dist/esm/ResponseActions/ResponseActionsGroups.js +18 -0
  195. package/dist/esm/ResponseActions/ResponseActionsGroups.test.d.ts +1 -0
  196. package/dist/esm/ResponseActions/ResponseActionsGroups.test.js +20 -0
  197. package/dist/esm/ResponseActions/index.d.ts +1 -0
  198. package/dist/esm/ResponseActions/index.js +1 -0
  199. package/dist/esm/ToolCall/ToolCall.d.ts +11 -0
  200. package/dist/esm/ToolCall/ToolCall.js +21 -3
  201. package/dist/esm/ToolCall/ToolCall.test.js +57 -0
  202. package/dist/esm/ToolResponse/ToolResponse.d.ts +17 -0
  203. package/dist/esm/ToolResponse/ToolResponse.js +46 -3
  204. package/dist/esm/ToolResponse/ToolResponse.test.js +100 -0
  205. package/dist/esm/index.d.ts +4 -0
  206. package/dist/esm/index.js +4 -0
  207. package/dist/tsconfig.tsbuildinfo +1 -1
  208. package/package.json +13 -3
  209. package/patternfly-docs/content/extensions/chatbot/chatbot.md +57 -0
  210. package/patternfly-docs/content/extensions/chatbot/design-guidelines.md +12 -12
  211. package/patternfly-docs/content/extensions/chatbot/examples/Analytics/Analytics.md +1 -1
  212. package/patternfly-docs/content/extensions/chatbot/examples/Customizing Messages/Customizing Messages.md +1 -1
  213. package/patternfly-docs/content/extensions/chatbot/examples/Messages/BotMessage.tsx +1 -0
  214. package/patternfly-docs/content/extensions/chatbot/examples/Messages/MessageWithCustomStructure.tsx +102 -0
  215. package/patternfly-docs/content/extensions/chatbot/examples/Messages/MessageWithDeepThinking.tsx +25 -11
  216. package/patternfly-docs/content/extensions/chatbot/examples/Messages/MessageWithFeedback.tsx +14 -1
  217. package/patternfly-docs/content/extensions/chatbot/examples/Messages/MessageWithMarkdownDeepThinking.tsx +26 -0
  218. package/patternfly-docs/content/extensions/chatbot/examples/Messages/MessageWithMarkdownToolCall.tsx +29 -0
  219. package/patternfly-docs/content/extensions/chatbot/examples/Messages/MessageWithMarkdownToolResponse.tsx +200 -0
  220. package/patternfly-docs/content/extensions/chatbot/examples/Messages/MessageWithMultipleActionGroups.tsx +61 -0
  221. package/patternfly-docs/content/extensions/chatbot/examples/Messages/MessageWithPersistedActions.tsx +22 -0
  222. package/patternfly-docs/content/extensions/chatbot/examples/Messages/MessageWithQuickResponses.tsx +11 -0
  223. package/patternfly-docs/content/extensions/chatbot/examples/Messages/MessageWithToolCall.tsx +14 -1
  224. package/patternfly-docs/content/extensions/chatbot/examples/Messages/MessageWithToolResponse.tsx +222 -105
  225. package/patternfly-docs/content/extensions/chatbot/examples/Messages/Messages.md +123 -14
  226. package/patternfly-docs/content/extensions/chatbot/examples/Messages/UserMessage.tsx +1 -0
  227. package/patternfly-docs/content/extensions/chatbot/examples/UI/ChatbotHeaderDrawerWithSearchActions.tsx +198 -0
  228. package/patternfly-docs/content/extensions/chatbot/examples/UI/ChatbotMessageBarIndicatorThinking.tsx +15 -0
  229. package/patternfly-docs/content/extensions/chatbot/examples/UI/CompactOnboarding.tsx +141 -0
  230. package/patternfly-docs/content/extensions/chatbot/examples/UI/Onboarding.tsx +151 -0
  231. package/patternfly-docs/content/extensions/chatbot/examples/UI/RH-Hat-Image.svg +9 -0
  232. package/patternfly-docs/content/extensions/chatbot/examples/UI/UI.md +67 -29
  233. package/patternfly-docs/content/extensions/chatbot/examples/demos/AttachmentDemos.md +18 -18
  234. package/patternfly-docs/content/extensions/chatbot/examples/demos/Chatbot.md +33 -19
  235. package/patternfly-docs/patternfly-docs.config.js +1 -1
  236. package/patternfly-docs/patternfly-docs.source.js +1 -1
  237. package/src/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.scss +43 -0
  238. package/src/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.test.tsx +95 -0
  239. package/src/ChatbotConversationHistoryNav/ChatbotConversationHistoryNav.tsx +51 -15
  240. package/src/ChatbotHeader/ChatbotHeaderMenu.tsx +56 -14
  241. package/src/ChatbotModal/ChatbotModal.scss +3 -0
  242. package/src/CodeModal/CodeModal.tsx +71 -26
  243. package/src/DeepThinking/DeepThinking.scss +1 -1
  244. package/src/DeepThinking/DeepThinking.test.tsx +109 -0
  245. package/src/DeepThinking/DeepThinking.tsx +54 -5
  246. package/src/MarkdownContent/MarkdownContent.test.tsx +207 -0
  247. package/src/MarkdownContent/MarkdownContent.tsx +269 -0
  248. package/src/MarkdownContent/index.ts +2 -0
  249. package/src/Message/CodeBlockMessage/CodeBlockMessage.scss +13 -0
  250. package/src/Message/CodeBlockMessage/CodeBlockMessage.test.tsx +171 -0
  251. package/src/Message/CodeBlockMessage/CodeBlockMessage.tsx +17 -4
  252. package/src/Message/ErrorMessage/ErrorMessage.test.tsx +38 -0
  253. package/src/Message/ErrorMessage/ErrorMessage.tsx +17 -2
  254. package/src/Message/LinkMessage/LinkMessage.scss +5 -0
  255. package/src/Message/LinkMessage/LinkMessage.tsx +24 -2
  256. package/src/Message/ListMessage/ListMessage.scss +8 -0
  257. package/src/Message/ListMessage/OrderedListMessage.tsx +16 -2
  258. package/src/Message/ListMessage/UnorderedListMessage.tsx +12 -2
  259. package/src/Message/Message.scss +11 -7
  260. package/src/Message/Message.test.tsx +202 -2
  261. package/src/Message/Message.tsx +129 -241
  262. package/src/Message/MessageAndActions/MessageAndActions.test.tsx +23 -0
  263. package/src/Message/MessageAndActions/MessageAndActions.tsx +22 -0
  264. package/src/Message/MessageAndActions/index.ts +1 -0
  265. package/src/Message/MessageAttachments/MessageAttachmentItem.test.tsx +23 -0
  266. package/src/Message/MessageAttachments/MessageAttachmentItem.tsx +25 -0
  267. package/src/Message/MessageAttachments/MessageAttachmentsContainer.test.tsx +23 -0
  268. package/src/Message/MessageAttachments/MessageAttachmentsContainer.tsx +25 -0
  269. package/src/Message/MessageAttachments/index.ts +2 -0
  270. package/src/Message/MessageInput.tsx +1 -1
  271. package/src/Message/MessageLoading.test.tsx +23 -0
  272. package/src/Message/MessageLoading.tsx +17 -2
  273. package/src/Message/QuickResponse/QuickResponse.scss +3 -1
  274. package/src/Message/QuickResponse/QuickResponse.test.tsx +131 -0
  275. package/src/Message/QuickResponse/QuickResponse.tsx +3 -2
  276. package/src/Message/QuickResponse/index.ts +1 -0
  277. package/src/Message/QuickStarts/QuickStartTile.tsx +1 -1
  278. package/src/Message/QuickStarts/index.ts +2 -0
  279. package/src/Message/TableMessage/TableMessage.scss +13 -1
  280. package/src/Message/TableMessage/TableMessage.tsx +18 -2
  281. package/src/Message/TextMessage/TextMessage.scss +12 -0
  282. package/src/Message/TextMessage/TextMessage.tsx +29 -2
  283. package/src/Message/UserFeedback/UserFeedback.scss +28 -1
  284. package/src/Message/UserFeedback/UserFeedback.tsx +23 -13
  285. package/src/Message/UserFeedback/UserFeedbackComplete.tsx +1 -4
  286. package/src/Message/UserFeedback/index.ts +2 -0
  287. package/src/Message/index.ts +8 -0
  288. package/src/MessageBar/AttachButton.scss +0 -1
  289. package/src/MessageBar/MessageBar.scss +48 -6
  290. package/src/MessageBar/MessageBar.test.tsx +12 -0
  291. package/src/MessageBar/MessageBar.tsx +38 -4
  292. package/src/MessageBar/MicrophoneButton.scss +0 -1
  293. package/src/MessageBar/SendButton.scss +0 -1
  294. package/src/MessageBar/StopButton.scss +0 -1
  295. package/src/Onboarding/Onboarding.scss +101 -0
  296. package/src/Onboarding/Onboarding.test.tsx +148 -0
  297. package/src/Onboarding/Onboarding.tsx +126 -0
  298. package/src/Onboarding/index.ts +3 -0
  299. package/src/ResponseActions/ResponseActions.scss +12 -1
  300. package/src/ResponseActions/ResponseActions.test.tsx +111 -12
  301. package/src/ResponseActions/ResponseActions.tsx +44 -10
  302. package/src/ResponseActions/ResponseActionsGroups.test.tsx +23 -0
  303. package/src/ResponseActions/ResponseActionsGroups.tsx +28 -0
  304. package/src/ResponseActions/index.ts +1 -0
  305. package/src/ToolCall/ToolCall.scss +1 -1
  306. package/src/ToolCall/ToolCall.test.tsx +91 -0
  307. package/src/ToolCall/ToolCall.tsx +49 -4
  308. package/src/ToolResponse/ToolResponse.scss +13 -3
  309. package/src/ToolResponse/ToolResponse.test.tsx +119 -0
  310. package/src/ToolResponse/ToolResponse.tsx +82 -7
  311. package/src/index.ts +6 -0
  312. package/src/main.scss +2 -0
  313. package/tsconfig.json +1 -1
  314. package/patternfly-docs/content/extensions/chatbot/about-chatbot.md +0 -44
@@ -1,5 +1,5 @@
1
1
  import type { FunctionComponent } from 'react';
2
- import { ButtonProps, DrawerProps, DrawerPanelContentProps, DrawerContentProps, DrawerContentBodyProps, DrawerHeadProps, DrawerActionsProps, DrawerCloseButtonProps, DrawerPanelBodyProps, SkeletonProps, MenuProps, TitleProps, MenuListProps, SearchInputProps, MenuItemProps, MenuGroupProps, MenuContentProps } from '@patternfly/react-core';
2
+ import { ButtonProps, DrawerProps, DrawerPanelContentProps, DrawerContentProps, DrawerContentBodyProps, DrawerHeadProps, DrawerActionsProps, DrawerCloseButtonProps, DrawerPanelBodyProps, SkeletonProps, TitleProps, SearchInputProps, MenuProps, MenuListProps, MenuItemProps, MenuGroupProps, MenuContentProps } from '@patternfly/react-core';
3
3
  import { ChatbotDisplayMode } from '../Chatbot/Chatbot';
4
4
  import { HistoryEmptyStateProps } from './EmptyState';
5
5
  export interface Conversation {
@@ -84,6 +84,8 @@ export interface ChatbotConversationHistoryNavProps extends DrawerProps {
84
84
  drawerCloseButtonProps?: DrawerCloseButtonProps;
85
85
  /** Additional props appleid to drawer panel body */
86
86
  drawerPanelBodyProps?: DrawerPanelBodyProps;
87
+ /** Flag indicating whether a divider should render between the drawer head and title. */
88
+ hasDrawerHeadDivider?: boolean;
87
89
  /** Whether to show drawer loading state */
88
90
  isLoading?: boolean;
89
91
  /** Additional props for loading state */
@@ -104,6 +106,12 @@ export interface ChatbotConversationHistoryNavProps extends DrawerProps {
104
106
  navTitleProps?: Partial<TitleProps>;
105
107
  /** Visually hidden text that gets announced by assistive technologies. Should be used to convey the result count when the search input value changes. */
106
108
  searchInputScreenReaderText?: string;
109
+ /** Custom action rendered before the search input. */
110
+ searchActionStart?: React.ReactNode;
111
+ /** Custom action rendered after the search input. */
112
+ searchActionEnd?: React.ReactNode;
113
+ /** A custom search toolbar to render below the title. This will override the default search actions and/or search input. */
114
+ searchToolbar?: React.ReactNode;
107
115
  /** Additional props passed to MenuContent */
108
116
  menuContentProps?: Omit<MenuContentProps, 'ref'>;
109
117
  }
@@ -12,14 +12,14 @@ var __rest = (this && this.__rest) || function (s, e) {
12
12
  import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
13
13
  import { useRef, Fragment } from 'react';
14
14
  // Import PatternFly components
15
- import { Button, Drawer, DrawerPanelContent, DrawerContent, DrawerPanelBody, DrawerHead, DrawerActions, DrawerCloseButton, DrawerContentBody, SearchInput, Title, Icon, MenuList, MenuGroup, MenuItem, Menu, MenuContent } from '@patternfly/react-core';
15
+ import { Button, Divider, Drawer, DrawerPanelContent, DrawerContent, DrawerPanelBody, DrawerHead, DrawerActions, DrawerCloseButton, DrawerContentBody, InputGroup, InputGroupItem, SearchInput, Title, Icon, MenuList, MenuGroup, MenuItem, Menu, MenuContent } from '@patternfly/react-core';
16
16
  import { OutlinedClockIcon, OutlinedCommentAltIcon, PenToSquareIcon } from '@patternfly/react-icons';
17
17
  import { ChatbotDisplayMode } from '../Chatbot/Chatbot';
18
18
  import ConversationHistoryDropdown from './ChatbotConversationHistoryDropdown';
19
19
  import LoadingState from './LoadingState';
20
20
  import HistoryEmptyState from './EmptyState';
21
21
  export const ChatbotConversationHistoryNav = (_a) => {
22
- var { onDrawerToggle, isDrawerOpen, setIsDrawerOpen, activeItemId, onSelectActiveItem, conversations, menuListProps, newChatButtonText = 'New chat', drawerContent, onNewChat, newChatButtonProps, searchInputPlaceholder = 'Search previous conversations...', searchInputAriaLabel = 'Search previous conversations', searchInputProps, handleTextInputChange, displayMode, reverseButtonOrder = false, drawerActionsTestId = 'chatbot-nav-drawer-actions', drawerPanelContentProps, drawerContentProps, drawerContentBodyProps, drawerHeadProps, drawerActionsProps, drawerCloseButtonProps, drawerPanelBodyProps, isLoading, loadingState, errorState, emptyState, noResultsState, isCompact, title = 'Chat history', navTitleProps, navTitleIcon = _jsx(OutlinedClockIcon, {}), searchInputScreenReaderText, menuProps, menuGroupProps, menuContentProps } = _a, props = __rest(_a, ["onDrawerToggle", "isDrawerOpen", "setIsDrawerOpen", "activeItemId", "onSelectActiveItem", "conversations", "menuListProps", "newChatButtonText", "drawerContent", "onNewChat", "newChatButtonProps", "searchInputPlaceholder", "searchInputAriaLabel", "searchInputProps", "handleTextInputChange", "displayMode", "reverseButtonOrder", "drawerActionsTestId", "drawerPanelContentProps", "drawerContentProps", "drawerContentBodyProps", "drawerHeadProps", "drawerActionsProps", "drawerCloseButtonProps", "drawerPanelBodyProps", "isLoading", "loadingState", "errorState", "emptyState", "noResultsState", "isCompact", "title", "navTitleProps", "navTitleIcon", "searchInputScreenReaderText", "menuProps", "menuGroupProps", "menuContentProps"]);
22
+ var { onDrawerToggle, isDrawerOpen, setIsDrawerOpen, activeItemId, onSelectActiveItem, conversations, menuListProps, newChatButtonText = 'New chat', drawerContent, onNewChat, newChatButtonProps, searchInputPlaceholder = 'Search previous conversations...', searchInputAriaLabel = 'Search previous conversations', searchInputProps, handleTextInputChange, displayMode, reverseButtonOrder = false, drawerActionsTestId = 'chatbot-nav-drawer-actions', drawerPanelContentProps, drawerContentProps, drawerContentBodyProps, drawerHeadProps, drawerActionsProps, drawerCloseButtonProps, drawerPanelBodyProps, hasDrawerHeadDivider, isLoading, loadingState, errorState, emptyState, noResultsState, isCompact, title = 'Chat history', navTitleProps, navTitleIcon = _jsx(OutlinedClockIcon, {}), searchInputScreenReaderText, searchActionStart, searchActionEnd, searchToolbar, menuProps, menuGroupProps, menuContentProps } = _a, props = __rest(_a, ["onDrawerToggle", "isDrawerOpen", "setIsDrawerOpen", "activeItemId", "onSelectActiveItem", "conversations", "menuListProps", "newChatButtonText", "drawerContent", "onNewChat", "newChatButtonProps", "searchInputPlaceholder", "searchInputAriaLabel", "searchInputProps", "handleTextInputChange", "displayMode", "reverseButtonOrder", "drawerActionsTestId", "drawerPanelContentProps", "drawerContentProps", "drawerContentBodyProps", "drawerHeadProps", "drawerActionsProps", "drawerCloseButtonProps", "drawerPanelBodyProps", "hasDrawerHeadDivider", "isLoading", "loadingState", "errorState", "emptyState", "noResultsState", "isCompact", "title", "navTitleProps", "navTitleIcon", "searchInputScreenReaderText", "searchActionStart", "searchActionEnd", "searchToolbar", "menuProps", "menuGroupProps", "menuContentProps"]);
23
23
  const drawerRef = useRef(null);
24
24
  const onExpand = () => {
25
25
  drawerRef.current && drawerRef.current.focus();
@@ -64,8 +64,15 @@ export const ChatbotConversationHistoryNav = (_a) => {
64
64
  return (_jsx(Menu, Object.assign({ isPlain: true, onSelect: onSelectActiveItem, activeItemId: activeItemId }, menuProps, { children: _jsx(MenuContent, Object.assign({}, menuContentProps, { children: buildConversations() })) })));
65
65
  };
66
66
  const renderDrawerContent = () => (_jsx(_Fragment, { children: _jsx(DrawerPanelBody, Object.assign({}, drawerPanelBodyProps, { children: renderMenuContent() })) }));
67
+ const searchInputContainer = handleTextInputChange && (_jsxs("div", { className: "pf-chatbot__input", children: [_jsx(SearchInput, Object.assign({ "aria-label": searchInputAriaLabel, onChange: (_event, value) => handleTextInputChange(value), placeholder: searchInputPlaceholder }, searchInputProps)), searchInputScreenReaderText && (_jsx("div", { className: "pf-chatbot__filter-announcement pf-chatbot-m-hidden", children: searchInputScreenReaderText }))] }));
68
+ const renderSearchAndActions = () => {
69
+ if (searchToolbar) {
70
+ return searchToolbar;
71
+ }
72
+ return searchActionStart || searchActionEnd ? (_jsx("div", { className: "pf-chatbot__history-search-actions", children: _jsxs(InputGroup, { children: [searchActionStart && _jsx(InputGroupItem, { children: searchActionStart }), searchInputContainer && _jsx(InputGroupItem, { isFill: true, children: searchInputContainer }), searchActionEnd && _jsx(InputGroupItem, { children: searchActionEnd })] }) })) : (searchInputContainer);
73
+ };
67
74
  const renderPanelContent = () => {
68
- const drawer = (_jsxs(_Fragment, { children: [_jsx(DrawerHead, Object.assign({}, drawerHeadProps, { children: _jsxs(DrawerActions, Object.assign({ "data-testid": drawerActionsTestId, className: reverseButtonOrder ? 'pf-v6-c-drawer__actions--reversed' : '' }, drawerActionsProps, { children: [_jsx(DrawerCloseButton, Object.assign({ onClick: onDrawerToggle }, drawerCloseButtonProps)), onNewChat && (_jsx(Button, Object.assign({ size: isCompact ? 'sm' : undefined, onClick: onNewChat, icon: _jsx(PenToSquareIcon, {}) }, newChatButtonProps, { children: newChatButtonText })))] })) })), _jsxs("div", { className: "pf-chatbot__heading-container", children: [_jsxs("div", { className: "pf-chatbot__title-container", children: [_jsx(Icon, { size: "lg", className: "pf-chatbot__title-icon", children: navTitleIcon }), _jsx(Title, Object.assign({ className: "pf-chatbot__title", headingLevel: "h2" }, navTitleProps, { children: title }))] }), !isLoading && handleTextInputChange && (_jsxs("div", { className: "pf-chatbot__input", children: [_jsx(SearchInput, Object.assign({ "aria-label": searchInputAriaLabel, onChange: (_event, value) => handleTextInputChange(value), placeholder: searchInputPlaceholder }, searchInputProps)), searchInputScreenReaderText && (_jsx("div", { className: "pf-chatbot__filter-announcement pf-chatbot-m-hidden", children: searchInputScreenReaderText }))] }))] }), isLoading ? _jsx(LoadingState, Object.assign({}, loadingState)) : renderDrawerContent()] }));
75
+ const drawer = (_jsxs(_Fragment, { children: [_jsx(DrawerHead, Object.assign({}, drawerHeadProps, { children: _jsxs(DrawerActions, Object.assign({ "data-testid": drawerActionsTestId, className: reverseButtonOrder ? 'pf-v6-c-drawer__actions--reversed' : '' }, drawerActionsProps, { children: [_jsx(DrawerCloseButton, Object.assign({ onClick: onDrawerToggle }, drawerCloseButtonProps)), onNewChat && (_jsx(Button, Object.assign({ size: isCompact ? 'sm' : undefined, onClick: onNewChat, icon: _jsx(PenToSquareIcon, {}) }, newChatButtonProps, { children: newChatButtonText })))] })) })), hasDrawerHeadDivider && _jsx(Divider, { className: "pf-chatbot__heading-divider" }), _jsxs("div", { className: "pf-chatbot__heading-container", children: [_jsxs("div", { className: "pf-chatbot__title-container", children: [_jsx(Icon, { size: "lg", className: "pf-chatbot__title-icon", children: navTitleIcon }), _jsx(Title, Object.assign({ className: "pf-chatbot__title", headingLevel: "h2" }, navTitleProps, { children: title }))] }), !isLoading && renderSearchAndActions()] }), isLoading ? _jsx(LoadingState, Object.assign({}, loadingState)) : renderDrawerContent()] }));
69
76
  return (_jsx(DrawerPanelContent, Object.assign({ "aria-live": "polite", focusTrap: { enabled: true }, defaultSize: "384px" }, drawerPanelContentProps, { children: drawer })));
70
77
  };
71
78
  // An onKeyDown property must be passed to the Drawer component to handle closing
@@ -222,6 +222,44 @@ describe('ChatbotConversationHistoryNav', () => {
222
222
  render(_jsx(ChatbotConversationHistoryNav, { onDrawerToggle: onDrawerToggle, isDrawerOpen: true, displayMode: ChatbotDisplayMode.fullscreen, setIsDrawerOpen: jest.fn(), conversations: initialConversations, handleTextInputChange: jest.fn(), searchInputProps: { value: 'I am a sample search' } }));
223
223
  expect(screen.getByRole('dialog', { name: /Chat history I am a sample search/i })).toBeInTheDocument();
224
224
  });
225
+ it('Does not render search actions by default', () => {
226
+ var _a, _b;
227
+ const handleSearch = jest.fn();
228
+ const groupedConversations = {
229
+ Today: [...initialConversations, { id: '2', text: 'Chatbot extension' }]
230
+ };
231
+ render(_jsx(ChatbotConversationHistoryNav, { onDrawerToggle: onDrawerToggle, isDrawerOpen: true, displayMode: ChatbotDisplayMode.fullscreen, setIsDrawerOpen: jest.fn(), reverseButtonOrder: false, conversations: groupedConversations, handleTextInputChange: handleSearch }));
232
+ const searchInput = screen.getByPlaceholderText(/Search/i);
233
+ expect((_a = searchInput.parentElement) === null || _a === void 0 ? void 0 : _a.previousElementSibling).toBeNull();
234
+ expect((_b = searchInput.parentElement) === null || _b === void 0 ? void 0 : _b.nextElementSibling).toBeNull();
235
+ });
236
+ it('Renders with action at start when searchActionStart is passed', () => {
237
+ const handleSearch = jest.fn();
238
+ const groupedConversations = {
239
+ Today: [...initialConversations, { id: '2', text: 'Chatbot extension' }]
240
+ };
241
+ render(_jsx(ChatbotConversationHistoryNav, { onDrawerToggle: onDrawerToggle, isDrawerOpen: true, displayMode: ChatbotDisplayMode.fullscreen, setIsDrawerOpen: jest.fn(), reverseButtonOrder: false, conversations: groupedConversations, handleTextInputChange: handleSearch, searchActionStart: _jsx("div", { children: "Search action start test" }) }));
242
+ expect(screen.getByText('Search action start test')).toBeVisible();
243
+ });
244
+ it('Renders with action at end when searchActionEnd is passed', () => {
245
+ const handleSearch = jest.fn();
246
+ const groupedConversations = {
247
+ Today: [...initialConversations, { id: '2', text: 'Chatbot extension' }]
248
+ };
249
+ render(_jsx(ChatbotConversationHistoryNav, { onDrawerToggle: onDrawerToggle, isDrawerOpen: true, displayMode: ChatbotDisplayMode.fullscreen, setIsDrawerOpen: jest.fn(), reverseButtonOrder: false, handleTextInputChange: handleSearch, conversations: groupedConversations, searchActionEnd: _jsx("div", { children: "Search action end test" }) }));
250
+ expect(screen.getByText('Search action end test')).toBeVisible();
251
+ });
252
+ it('Overrides default search input and actions when searchToolbar is passed', () => {
253
+ const handleSearch = jest.fn();
254
+ const groupedConversations = {
255
+ Today: [...initialConversations, { id: '2', text: 'Chatbot extension' }]
256
+ };
257
+ render(_jsx(ChatbotConversationHistoryNav, { onDrawerToggle: onDrawerToggle, isDrawerOpen: true, displayMode: ChatbotDisplayMode.fullscreen, setIsDrawerOpen: jest.fn(), reverseButtonOrder: false, conversations: groupedConversations, handleTextInputChange: handleSearch, searchActionStart: _jsx("div", { children: "Search action start test" }), searchActionEnd: _jsx("div", { children: "Search action end test" }), searchToolbar: _jsx("div", { children: "Custom toolbar" }) }));
258
+ expect(screen.queryByPlaceholderText(/Search/i)).not.toBeInTheDocument();
259
+ expect(screen.queryByText('Search action start test')).not.toBeInTheDocument();
260
+ expect(screen.queryByText('Search action end test')).not.toBeInTheDocument();
261
+ expect(screen.getByText('Custom toolbar')).toBeInTheDocument();
262
+ });
225
263
  it('overrides nav title heading level when navTitleProps.headingLevel is passed', () => {
226
264
  render(_jsx(ChatbotConversationHistoryNav, { onDrawerToggle: onDrawerToggle, isDrawerOpen: true, displayMode: ChatbotDisplayMode.fullscreen, setIsDrawerOpen: jest.fn(), conversations: { Today: initialConversations }, navTitleProps: { headingLevel: 'h1' } }));
227
265
  expect(screen.queryByRole('heading', { name: /Chat history/i, level: 2 })).not.toBeInTheDocument();
@@ -10,13 +10,40 @@ var __rest = (this && this.__rest) || function (s, e) {
10
10
  return t;
11
11
  };
12
12
  import { jsx as _jsx } from "react/jsx-runtime";
13
- import { forwardRef } from 'react';
13
+ import { forwardRef, useEffect, useMemo, useRef, useState } from 'react';
14
14
  import { Button, Icon, Tooltip } from '@patternfly/react-core';
15
15
  import BarsIcon from '@patternfly/react-icons/dist/esm/icons/bars-icon';
16
16
  const ChatbotHeaderMenuBase = (_a) => {
17
17
  var { className, onMenuToggle, tooltipProps, menuAriaLabel = 'Chat history menu', innerRef, tooltipContent = 'Chat history menu', isCompact } = _a, props = __rest(_a, ["className", "onMenuToggle", "tooltipProps", "menuAriaLabel", "innerRef", "tooltipContent", "isCompact"]);
18
- return (_jsx("div", { className: `pf-chatbot__menu ${className}`, children: _jsx(Tooltip, Object.assign({ content: tooltipContent, position: "bottom",
18
+ const [isDrawerAnimating, setIsDrawerAnimating] = useState(false);
19
+ // I'd like to use a prop here later if this works
20
+ const drawerState = props['aria-expanded'];
21
+ const isDrawerOpen = drawerState === true;
22
+ const prevDrawerStateRef = useRef(isDrawerOpen);
23
+ const buttonRef = useRef(null);
24
+ useEffect(() => {
25
+ if (drawerState !== undefined) {
26
+ const wasDrawerOpen = prevDrawerStateRef.current === true;
27
+ const isDrawerClosing = wasDrawerOpen && !isDrawerOpen;
28
+ setIsDrawerAnimating(true);
29
+ const timeout = setTimeout(() => {
30
+ setIsDrawerAnimating(false);
31
+ if (isDrawerClosing) {
32
+ requestAnimationFrame(() => {
33
+ var _a;
34
+ (_a = buttonRef.current) === null || _a === void 0 ? void 0 : _a.focus();
35
+ });
36
+ }
37
+ }, 350);
38
+ prevDrawerStateRef.current = isDrawerOpen;
39
+ return () => clearTimeout(timeout);
40
+ }
41
+ }, [drawerState, isDrawerOpen]);
42
+ const button = useMemo(() => (_jsx(Button, Object.assign({ className: `pf-chatbot__button--toggle-menu ${isCompact ? 'pf-m-compact' : ''}`, variant: "plain", onClick: onMenuToggle, "aria-label": menuAriaLabel, ref: innerRef !== null && innerRef !== void 0 ? innerRef : buttonRef, icon: _jsx(Icon, { size: isCompact ? 'lg' : 'xl', isInline: true, children: _jsx(BarsIcon, {}) }), size: isCompact ? 'sm' : undefined }, props))),
43
+ // eslint-disable-next-line react-hooks/exhaustive-deps
44
+ [isCompact, menuAriaLabel, onMenuToggle, innerRef, buttonRef]);
45
+ return (_jsx("div", { className: `pf-chatbot__menu ${className}`, children: isDrawerAnimating ? (button) : (_jsx(Tooltip, Object.assign({ content: tooltipContent, position: "bottom",
19
46
  // prevents VO announcements of both aria label and tooltip
20
- aria: "none" }, tooltipProps, { children: _jsx(Button, Object.assign({ className: `pf-chatbot__button--toggle-menu ${isCompact ? 'pf-m-compact' : ''}`, variant: "plain", onClick: onMenuToggle, "aria-label": menuAriaLabel, ref: innerRef, icon: _jsx(Icon, { size: isCompact ? 'lg' : 'xl', isInline: true, children: _jsx(BarsIcon, {}) }), size: isCompact ? 'sm' : undefined }, props)) })) }));
47
+ aria: "none" }, tooltipProps, { children: button }))) }));
21
48
  };
22
49
  export const ChatbotHeaderMenu = forwardRef((props, ref) => (_jsx(ChatbotHeaderMenuBase, Object.assign({ innerRef: ref }, props))));
@@ -37,6 +37,8 @@ export interface CodeModalProps {
37
37
  modalBodyClassName?: string;
38
38
  /** Class applied to modal footer */
39
39
  modalFooterClassName?: string;
40
+ /** Aria label applied to spinner when loading Monaco */
41
+ spinnerAriaLabel?: string;
40
42
  }
41
43
  export declare const CodeModal: FunctionComponent<CodeModalProps>;
42
44
  export default CodeModal;
@@ -1,3 +1,12 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
1
10
  var __rest = (this && this.__rest) || function (s, e) {
2
11
  var t = {};
3
12
  for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
@@ -12,22 +21,45 @@ var __rest = (this && this.__rest) || function (s, e) {
12
21
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
13
22
  import { useState, useEffect, useRef } from 'react';
14
23
  import path from 'path-browserify';
15
- import * as monaco from 'monaco-editor';
16
- import { loader } from '@monaco-editor/react';
17
24
  // Import PatternFly components
18
25
  import { CodeEditor } from '@patternfly/react-code-editor';
19
- import { Button, getResizeObserver, ModalBody, ModalFooter, ModalHeader, Stack, StackItem } from '@patternfly/react-core';
26
+ import { Bullseye, Button, getResizeObserver, ModalBody, ModalFooter, ModalHeader, Spinner, Stack, StackItem } from '@patternfly/react-core';
20
27
  import FileDetails, { extensionToLanguage } from '../FileDetails';
21
28
  import { ChatbotDisplayMode } from '../Chatbot';
22
29
  import ChatbotModal from '../ChatbotModal/ChatbotModal';
23
- // Configure Monaco loader to use the npm package instead of CDN
24
- loader.config({ monaco });
30
+ // 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
31
+ let monacoInstance = null;
32
+ const loadMonaco = () => __awaiter(void 0, void 0, void 0, function* () {
33
+ if (!monacoInstance) {
34
+ const [monaco, { loader }] = yield Promise.all([import('monaco-editor'), import('@monaco-editor/react')]);
35
+ monacoInstance = monaco;
36
+ loader.config({ monaco });
37
+ }
38
+ return monacoInstance;
39
+ });
25
40
  export const CodeModal = (_a) => {
26
- var { fileName, code, codeEditorControlClassName: codeEditorClassName, handleModalToggle, isCopyEnabled, isLineNumbersVisible, isModalOpen, isReadOnly, onPrimaryAction, onSecondaryAction, primaryActionBtn, secondaryActionBtn, title, displayMode = ChatbotDisplayMode.default, isCompact, modalHeaderClassName, modalBodyClassName, modalFooterClassName } = _a, props = __rest(_a, ["fileName", "code", "codeEditorControlClassName", "handleModalToggle", "isCopyEnabled", "isLineNumbersVisible", "isModalOpen", "isReadOnly", "onPrimaryAction", "onSecondaryAction", "primaryActionBtn", "secondaryActionBtn", "title", "displayMode", "isCompact", "modalHeaderClassName", "modalBodyClassName", "modalFooterClassName"]);
41
+ var { fileName, code, codeEditorControlClassName: codeEditorClassName, handleModalToggle, isCopyEnabled, isLineNumbersVisible, isModalOpen, isReadOnly, onPrimaryAction, onSecondaryAction, primaryActionBtn, secondaryActionBtn, title, displayMode = ChatbotDisplayMode.default, isCompact, modalHeaderClassName, modalBodyClassName, modalFooterClassName, spinnerAriaLabel = 'Loading' } = _a, props = __rest(_a, ["fileName", "code", "codeEditorControlClassName", "handleModalToggle", "isCopyEnabled", "isLineNumbersVisible", "isModalOpen", "isReadOnly", "onPrimaryAction", "onSecondaryAction", "primaryActionBtn", "secondaryActionBtn", "title", "displayMode", "isCompact", "modalHeaderClassName", "modalBodyClassName", "modalFooterClassName", "spinnerAriaLabel"]);
27
42
  const [newCode, setNewCode] = useState(code);
28
43
  const [editorInstance, setEditorInstance] = useState(null);
29
44
  const [isEditorReady, setIsEditorReady] = useState(false);
45
+ const [isMonacoLoading, setIsMonacoLoading] = useState(false);
46
+ const [isMonacoLoaded, setIsMonacoLoaded] = useState(false);
30
47
  const containerRef = useRef(null);
48
+ useEffect(() => {
49
+ if (isModalOpen && !isMonacoLoaded && !isMonacoLoading) {
50
+ setIsMonacoLoading(true);
51
+ loadMonaco()
52
+ .then(() => {
53
+ setIsMonacoLoaded(true);
54
+ setIsMonacoLoading(false);
55
+ })
56
+ .catch((error) => {
57
+ // eslint-disable-next-line no-console
58
+ console.error('Failed to load Monaco editor:', error);
59
+ setIsMonacoLoading(false);
60
+ });
61
+ }
62
+ }, [isModalOpen, isMonacoLoaded, isMonacoLoading]);
31
63
  useEffect(() => {
32
64
  if (!isModalOpen || !isEditorReady || !editorInstance || !containerRef.current) {
33
65
  return;
@@ -77,13 +109,22 @@ export const CodeModal = (_a) => {
77
109
  setNewCode(value);
78
110
  }
79
111
  };
80
- const modal = (_jsxs(ChatbotModal, { isOpen: isModalOpen, onClose: handleModalToggle, ouiaId: "CodeModal", "aria-labelledby": "code-modal-title", "aria-describedby": "code-modal", className: `pf-chatbot__code-modal ${isCompact ? 'pf-m-compact' : ''} pf-chatbot__code-modal--${displayMode}`, displayMode: displayMode, isCompact: isCompact, children: [_jsx(ModalHeader, { className: modalHeaderClassName, title: title, labelId: "code-modal-title" }), _jsx(ModalBody, { className: modalBodyClassName, id: "code-modal-body", children: _jsxs(Stack, { className: "pf-chatbot__code-modal-body", children: [_jsx(StackItem, { className: "pf-chatbot__code-modal-file-details", children: _jsx(FileDetails, { fileName: fileName }) }), _jsx("div", { className: "pf-v6-l-stack__item pf-chatbot__code-modal-editor", ref: containerRef, children: _jsx(CodeEditor, Object.assign({ isDarkTheme: true, isLineNumbersVisible: isLineNumbersVisible, isLanguageLabelVisible: true, isCopyEnabled: isCopyEnabled, isReadOnly: isReadOnly, code: newCode, language: extensionToLanguage[path.extname(fileName).slice(1)], onEditorDidMount: onEditorDidMount, onCodeChange: onCodeChange, className: codeEditorClassName, isFullHeight: true, options: {
81
- glyphMargin: false,
82
- folding: false,
83
- // prevents Monaco from handling resizing itself
84
- // was causing ResizeObserver issues
85
- automaticLayout: false
86
- } }, props)) })] }) }), _jsxs(ModalFooter, { className: modalFooterClassName, children: [_jsx(Button, { isBlock: true, variant: "primary", onClick: handlePrimaryAction, form: "code-modal-form", children: primaryActionBtn }, "code-modal-primary"), _jsx(Button, { isBlock: true, variant: "link", onClick: handleSecondaryAction, children: secondaryActionBtn }, "code-modal-secondary")] })] }));
112
+ const renderMonacoEditor = () => {
113
+ if (isMonacoLoading) {
114
+ return (_jsx(Bullseye, { children: _jsx(Spinner, { "aria-label": spinnerAriaLabel }) }));
115
+ }
116
+ if (isMonacoLoaded) {
117
+ return (_jsx(CodeEditor, Object.assign({ isDarkTheme: true, isLineNumbersVisible: isLineNumbersVisible, isLanguageLabelVisible: true, isCopyEnabled: isCopyEnabled, isReadOnly: isReadOnly, code: newCode, language: extensionToLanguage[path.extname(fileName).slice(1)], onEditorDidMount: onEditorDidMount, onCodeChange: onCodeChange, className: codeEditorClassName, isFullHeight: true, options: {
118
+ glyphMargin: false,
119
+ folding: false,
120
+ // prevents Monaco from handling resizing itself
121
+ // was causing ResizeObserver issues
122
+ automaticLayout: false
123
+ } }, props)));
124
+ }
125
+ return null;
126
+ };
127
+ const modal = (_jsxs(ChatbotModal, { isOpen: isModalOpen, onClose: handleModalToggle, ouiaId: "CodeModal", "aria-labelledby": "code-modal-title", "aria-describedby": "code-modal", className: `pf-chatbot__code-modal ${isCompact ? 'pf-m-compact' : ''} pf-chatbot__code-modal--${displayMode}`, displayMode: displayMode, isCompact: isCompact, children: [_jsx(ModalHeader, { className: modalHeaderClassName, title: title, labelId: "code-modal-title" }), _jsx(ModalBody, { className: modalBodyClassName, id: "code-modal-body", children: _jsxs(Stack, { className: "pf-chatbot__code-modal-body", children: [_jsx(StackItem, { className: "pf-chatbot__code-modal-file-details", children: _jsx(FileDetails, { fileName: fileName }) }), _jsx("div", { className: "pf-v6-l-stack__item pf-chatbot__code-modal-editor", ref: containerRef, children: renderMonacoEditor() })] }) }), _jsxs(ModalFooter, { className: modalFooterClassName, children: [_jsx(Button, { isBlock: true, variant: "primary", onClick: handlePrimaryAction, form: "code-modal-form", children: primaryActionBtn }, "code-modal-primary"), _jsx(Button, { isBlock: true, variant: "link", onClick: handleSecondaryAction, children: secondaryActionBtn }, "code-modal-secondary")] })] }));
87
128
  return modal;
88
129
  };
89
130
  export default CodeModal;
@@ -1,8 +1,11 @@
1
1
  import { CardBodyProps, CardProps, ExpandableSectionProps } from '@patternfly/react-core';
2
2
  import { type FunctionComponent } from 'react';
3
+ import type { MarkdownContentProps } from '../MarkdownContent';
3
4
  export interface DeepThinkingProps {
4
5
  /** Toggle content shown for expandable section */
5
6
  toggleContent: React.ReactNode;
7
+ /** Flag indicating whether the expandable content is expanded by default. */
8
+ isDefaultExpanded?: boolean;
6
9
  /** Additional props passed to expandable section */
7
10
  expandableSectionProps?: Omit<ExpandableSectionProps, 'ref'>;
8
11
  /** Subheading rendered inside expandable section */
@@ -13,6 +16,16 @@ export interface DeepThinkingProps {
13
16
  cardProps?: CardProps;
14
17
  /** Additional props passed to main card body */
15
18
  cardBodyProps?: CardBodyProps;
19
+ /** Whether to enable markdown rendering for toggleContent. When true and toggleContent is a string, it will be parsed as markdown. */
20
+ isToggleContentMarkdown?: boolean;
21
+ /** Whether to enable markdown rendering for subheading. When true, subheading will be parsed as markdown. */
22
+ isSubheadingMarkdown?: boolean;
23
+ /** Whether to enable markdown rendering for body. When true and body is a string, it will be parsed as markdown. */
24
+ isBodyMarkdown?: boolean;
25
+ /** Props passed to MarkdownContent component when markdown is enabled */
26
+ markdownContentProps?: Omit<MarkdownContentProps, 'content'>;
27
+ /** Whether to retain styles in the MarkdownContent component. Defaults to false. */
28
+ shouldRetainStyles?: boolean;
16
29
  }
17
30
  export declare const DeepThinking: FunctionComponent<DeepThinkingProps>;
18
31
  export default DeepThinking;
@@ -4,11 +4,36 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
4
4
  // ============================================================================
5
5
  import { Card, CardBody, ExpandableSection } from '@patternfly/react-core';
6
6
  import { useState } from 'react';
7
- export const DeepThinking = ({ body, cardProps, expandableSectionProps, subheading, toggleContent, cardBodyProps }) => {
8
- const [isExpanded, setIsExpanded] = useState(true);
7
+ import MarkdownContent from '../MarkdownContent';
8
+ export const DeepThinking = ({ body, cardProps, expandableSectionProps, subheading, toggleContent, isDefaultExpanded = true, cardBodyProps, isToggleContentMarkdown, isSubheadingMarkdown, isBodyMarkdown, markdownContentProps, shouldRetainStyles = false }) => {
9
+ const [isExpanded, setIsExpanded] = useState(isDefaultExpanded);
9
10
  const onToggle = (_event, isExpanded) => {
10
11
  setIsExpanded(isExpanded);
11
12
  };
12
- return (_jsx(Card, Object.assign({ isCompact: true, className: "pf-chatbot__deep-thinking" }, cardProps, { children: _jsx(CardBody, Object.assign({}, cardBodyProps, { children: _jsx(ExpandableSection, Object.assign({ toggleContent: toggleContent, onToggle: onToggle, isExpanded: isExpanded, isIndented: true, className: "pf-chatbot__deep-thinking-expandable-section" }, expandableSectionProps, { children: _jsxs("div", { className: "pf-chatbot__deep-thinking-section", children: [subheading && (_jsx("div", { className: "pf-chatbot__deep-thinking-subheading", children: _jsx("span", { children: subheading }) })), body && _jsx("div", { className: "pf-chatbot__deep-thinking-body", children: body })] }) })) })) })));
13
+ const renderToggleContent = () => {
14
+ if (isToggleContentMarkdown && typeof toggleContent === 'string') {
15
+ return (_jsx(MarkdownContent, Object.assign({ shouldRetainStyles: shouldRetainStyles, content: toggleContent }, markdownContentProps)));
16
+ }
17
+ return toggleContent;
18
+ };
19
+ const renderSubheading = () => {
20
+ if (!subheading) {
21
+ return null;
22
+ }
23
+ if (isSubheadingMarkdown) {
24
+ return _jsx(MarkdownContent, Object.assign({ shouldRetainStyles: shouldRetainStyles, content: subheading }, markdownContentProps));
25
+ }
26
+ return subheading;
27
+ };
28
+ const renderBody = () => {
29
+ if (!body) {
30
+ return null;
31
+ }
32
+ if (isBodyMarkdown && typeof body === 'string') {
33
+ return _jsx(MarkdownContent, Object.assign({ shouldRetainStyles: shouldRetainStyles, content: body }, markdownContentProps));
34
+ }
35
+ return body;
36
+ };
37
+ return (_jsx(Card, Object.assign({ isCompact: true, className: "pf-chatbot__deep-thinking" }, cardProps, { children: _jsx(CardBody, Object.assign({}, cardBodyProps, { children: _jsx(ExpandableSection, Object.assign({ toggleContent: renderToggleContent(), onToggle: onToggle, isExpanded: isExpanded, isIndented: true, className: "pf-chatbot__deep-thinking-expandable-section" }, expandableSectionProps, { children: _jsxs("div", { className: "pf-chatbot__deep-thinking-section", children: [subheading && (_jsx("div", { className: "pf-chatbot__deep-thinking-subheading", children: _jsx("span", { children: renderSubheading() }) })), body && _jsx("div", { className: "pf-chatbot__deep-thinking-body", children: renderBody() })] }) })) })) })));
13
38
  };
14
39
  export default DeepThinking;
@@ -1,5 +1,15 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
1
10
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
11
  import { render, screen } from '@testing-library/react';
12
+ import userEvent from '@testing-library/user-event';
3
13
  import '@testing-library/jest-dom';
4
14
  import DeepThinking from './DeepThinking';
5
15
  describe('DeepThinking', () => {
@@ -40,4 +50,74 @@ describe('DeepThinking', () => {
40
50
  const subheadingContainer = container.querySelector('.pf-chatbot__tool-response-subheading');
41
51
  expect(subheadingContainer).toBeFalsy();
42
52
  });
53
+ it('should pass through cardBodyProps', () => {
54
+ render(_jsx(DeepThinking, Object.assign({}, defaultProps, { body: "Thinking content", cardBodyProps: { className: 'custom-card-body-class' } })));
55
+ const cardBody = screen.getByText('Thinking content').closest('.pf-v6-c-card__body');
56
+ expect(cardBody).toHaveClass('custom-card-body-class');
57
+ });
58
+ it('Renders expanded by default', () => {
59
+ render(_jsx(DeepThinking, Object.assign({}, defaultProps, { body: "Thinking content" })));
60
+ expect(screen.getByRole('button', { name: defaultProps.toggleContent })).toHaveAttribute('aria-expanded', 'true');
61
+ expect(screen.getByText('Thinking content')).toBeVisible();
62
+ });
63
+ it('Renders collapsed when isDefaultExpanded is false', () => {
64
+ render(_jsx(DeepThinking, Object.assign({ isDefaultExpanded: false }, defaultProps, { body: "Thinking content" })));
65
+ expect(screen.getByRole('button', { name: defaultProps.toggleContent })).toHaveAttribute('aria-expanded', 'false');
66
+ expect(screen.getByText('Thinking content')).not.toBeVisible();
67
+ });
68
+ it('expandableSectionProps.isExpanded overrides isDefaultExpanded', () => {
69
+ render(_jsx(DeepThinking, Object.assign({}, defaultProps, { isDefaultExpanded: false, body: "Thinking content", expandableSectionProps: { isExpanded: true } })));
70
+ expect(screen.getByRole('button', { name: defaultProps.toggleContent })).toHaveAttribute('aria-expanded', 'true');
71
+ expect(screen.getByText('Thinking content')).toBeVisible();
72
+ });
73
+ it('expandableSectionProps.onToggle overrides internal onToggle behavior', () => __awaiter(void 0, void 0, void 0, function* () {
74
+ const user = userEvent.setup();
75
+ const customOnToggle = jest.fn();
76
+ render(_jsx(DeepThinking, Object.assign({}, defaultProps, { isDefaultExpanded: false, body: "Thinking content", expandableSectionProps: { onToggle: customOnToggle } })));
77
+ const toggleButton = screen.getByRole('button', { name: defaultProps.toggleContent });
78
+ expect(toggleButton).toHaveAttribute('aria-expanded', 'false');
79
+ yield user.click(toggleButton);
80
+ expect(customOnToggle).toHaveBeenCalled();
81
+ expect(toggleButton).toHaveAttribute('aria-expanded', 'false');
82
+ expect(screen.getByText('Thinking content')).not.toBeVisible();
83
+ }));
84
+ it('should render toggleContent as markdown when isToggleContentMarkdown is true', () => {
85
+ const toggleContent = '**Bold thinking**';
86
+ const { container } = render(_jsx(DeepThinking, { toggleContent: toggleContent, isToggleContentMarkdown: true }));
87
+ expect(container.querySelector('strong')).toBeTruthy();
88
+ expect(screen.getByText('Bold thinking')).toBeTruthy();
89
+ });
90
+ it('should not render toggleContent as markdown when isToggleContentMarkdown is false', () => {
91
+ const toggleContent = '**Bold thinking**';
92
+ const { container } = render(_jsx(DeepThinking, { toggleContent: toggleContent }));
93
+ expect(container.querySelector('strong')).toBeFalsy();
94
+ expect(screen.getByText('**Bold thinking**')).toBeTruthy();
95
+ });
96
+ it('should render subheading as markdown when isSubheadingMarkdown is true', () => {
97
+ const subheading = '**Bold subheading**';
98
+ const { container } = render(_jsx(DeepThinking, Object.assign({}, defaultProps, { subheading: subheading, isSubheadingMarkdown: true })));
99
+ expect(container.querySelector('strong')).toBeTruthy();
100
+ expect(screen.getByText('Bold subheading')).toBeTruthy();
101
+ });
102
+ it('should not render subheading as markdown when isSubheadingMarkdown is false', () => {
103
+ const subheading = '**Bold subheading**';
104
+ render(_jsx(DeepThinking, Object.assign({}, defaultProps, { subheading: subheading })));
105
+ expect(screen.getByText('**Bold subheading**')).toBeTruthy();
106
+ });
107
+ it('should render body as markdown when isBodyMarkdown is true', () => {
108
+ const body = '**Bold body**';
109
+ const { container } = render(_jsx(DeepThinking, Object.assign({}, defaultProps, { body: body, isBodyMarkdown: true })));
110
+ expect(container.querySelector('strong')).toBeTruthy();
111
+ expect(screen.getByText('Bold body')).toBeTruthy();
112
+ });
113
+ it('should not render body as markdown when isBodyMarkdown is false', () => {
114
+ const body = '**Bold body**';
115
+ render(_jsx(DeepThinking, Object.assign({}, defaultProps, { body: body })));
116
+ expect(screen.getByText('**Bold body**')).toBeTruthy();
117
+ });
118
+ it('should pass markdownContentProps to MarkdownContent component', () => {
119
+ const body = '**Bold body**';
120
+ const { container } = render(_jsx(DeepThinking, Object.assign({}, defaultProps, { body: body, isBodyMarkdown: true, markdownContentProps: { isPrimary: true } })));
121
+ expect(container.querySelector('.pf-m-primary')).toBeTruthy();
122
+ });
43
123
  });
@@ -0,0 +1,44 @@
1
+ import { type FunctionComponent, ReactNode } from 'react';
2
+ import { Options } from 'react-markdown';
3
+ import { CodeBlockMessageProps } from '../Message/CodeBlockMessage/CodeBlockMessage';
4
+ import { TableProps } from '@patternfly/react-table';
5
+ import 'highlight.js/styles/vs2015.css';
6
+ import { PluggableList } from 'unified';
7
+ import { ButtonProps } from '@patternfly/react-core';
8
+ /**
9
+ * MarkdownContent renders content either as plain text or with content with markdown support.
10
+ *
11
+ * Use this component when passing children to Message to customize its structure.
12
+ */
13
+ export interface MarkdownContentProps {
14
+ /** The content to render. Supports markdown formatting by default, or plain text when isMarkdownDisabled is true. */
15
+ content?: string;
16
+ /** Disables markdown parsing, allowing only plain text input */
17
+ isMarkdownDisabled?: boolean;
18
+ /** Props for code blocks */
19
+ codeBlockProps?: CodeBlockMessageProps;
20
+ /** Props for table message. It is important to include a detailed aria-label that describes the purpose of the table. */
21
+ tableProps?: Required<Pick<TableProps, 'aria-label'>> & TableProps;
22
+ /** Additional rehype plugins passed from the consumer */
23
+ additionalRehypePlugins?: PluggableList;
24
+ /** Additional remark plugins passed from the consumer */
25
+ additionalRemarkPlugins?: PluggableList;
26
+ /** Whether to open links in message in new tab. */
27
+ openLinkInNewTab?: boolean;
28
+ /** Props for links */
29
+ linkProps?: ButtonProps;
30
+ /** Allows passing additional props down to markdown parser react-markdown, such as allowedElements and disallowedElements. See https://github.com/remarkjs/react-markdown?tab=readme-ov-file#options for options */
31
+ reactMarkdownProps?: Options;
32
+ /** Allows passing additional props down to remark-gfm. See https://github.com/remarkjs/remark-gfm?tab=readme-ov-file#options for options */
33
+ remarkGfmProps?: Options;
34
+ /** Whether to strip out images in markdown */
35
+ hasNoImages?: boolean;
36
+ /** Sets background colors to be appropriate on primary chatbot background */
37
+ isPrimary?: boolean;
38
+ /** Custom component to render when markdown is disabled */
39
+ textComponent?: ReactNode;
40
+ /** Flag indicating whether content should retain various styles of its context (typically font-size and text color). */
41
+ shouldRetainStyles?: boolean;
42
+ }
43
+ export declare const MarkdownContent: FunctionComponent<MarkdownContentProps>;
44
+ export default MarkdownContent;