@red-hat-developer-hub/backstage-plugin-intelligent-assistant 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (238) hide show
  1. package/CHANGELOG.md +681 -0
  2. package/README.md +378 -0
  3. package/config.d.ts +70 -0
  4. package/dist/alpha.d.ts +285 -0
  5. package/dist/alpha.esm.js +3 -0
  6. package/dist/alpha.esm.js.map +1 -0
  7. package/dist/api/LightspeedApiClient.esm.js +234 -0
  8. package/dist/api/LightspeedApiClient.esm.js.map +1 -0
  9. package/dist/api/NotebooksApiClient.esm.js +179 -0
  10. package/dist/api/NotebooksApiClient.esm.js.map +1 -0
  11. package/dist/api/api.esm.js +8 -0
  12. package/dist/api/api.esm.js.map +1 -0
  13. package/dist/api/notebooksApi.esm.js +10 -0
  14. package/dist/api/notebooksApi.esm.js.map +1 -0
  15. package/dist/components/Attachment.esm.js +108 -0
  16. package/dist/components/Attachment.esm.js.map +1 -0
  17. package/dist/components/AttachmentContext.esm.js +125 -0
  18. package/dist/components/AttachmentContext.esm.js.map +1 -0
  19. package/dist/components/CollapsedHistoryStrip.esm.js +87 -0
  20. package/dist/components/CollapsedHistoryStrip.esm.js.map +1 -0
  21. package/dist/components/DeleteModal.esm.js +92 -0
  22. package/dist/components/DeleteModal.esm.js.map +1 -0
  23. package/dist/components/FilePreview.esm.js +49 -0
  24. package/dist/components/FilePreview.esm.js.map +1 -0
  25. package/dist/components/LightSpeedChat.esm.js +1898 -0
  26. package/dist/components/LightSpeedChat.esm.js.map +1 -0
  27. package/dist/components/LightspeedChatBox.esm.js +252 -0
  28. package/dist/components/LightspeedChatBox.esm.js.map +1 -0
  29. package/dist/components/LightspeedChatBoxHeader.esm.js +210 -0
  30. package/dist/components/LightspeedChatBoxHeader.esm.js.map +1 -0
  31. package/dist/components/LightspeedChatContainer.esm.js +162 -0
  32. package/dist/components/LightspeedChatContainer.esm.js.map +1 -0
  33. package/dist/components/LightspeedChatModelsState.esm.js +198 -0
  34. package/dist/components/LightspeedChatModelsState.esm.js.map +1 -0
  35. package/dist/components/LightspeedDrawerContext.esm.js +15 -0
  36. package/dist/components/LightspeedDrawerContext.esm.js.map +1 -0
  37. package/dist/components/LightspeedDrawerProvider.esm.js +44 -0
  38. package/dist/components/LightspeedDrawerProvider.esm.js.map +1 -0
  39. package/dist/components/LightspeedDrawerStateExposer.esm.js +34 -0
  40. package/dist/components/LightspeedDrawerStateExposer.esm.js.map +1 -0
  41. package/dist/components/LightspeedFAB.esm.js +6 -0
  42. package/dist/components/LightspeedFAB.esm.js.map +1 -0
  43. package/dist/components/LightspeedFABContent.esm.js +65 -0
  44. package/dist/components/LightspeedFABContent.esm.js.map +1 -0
  45. package/dist/components/LightspeedIcon.esm.js +46 -0
  46. package/dist/components/LightspeedIcon.esm.js.map +1 -0
  47. package/dist/components/LightspeedPage.esm.js +31 -0
  48. package/dist/components/LightspeedPage.esm.js.map +1 -0
  49. package/dist/components/McpServersSettings.esm.js +953 -0
  50. package/dist/components/McpServersSettings.esm.js.map +1 -0
  51. package/dist/components/McpSettingsIcon.esm.js +18 -0
  52. package/dist/components/McpSettingsIcon.esm.js.map +1 -0
  53. package/dist/components/MessageBarModelSelector.esm.js +92 -0
  54. package/dist/components/MessageBarModelSelector.esm.js.map +1 -0
  55. package/dist/components/PermissionRequiredIcon.esm.js +18 -0
  56. package/dist/components/PermissionRequiredIcon.esm.js.map +1 -0
  57. package/dist/components/PermissionRequiredState.esm.js +88 -0
  58. package/dist/components/PermissionRequiredState.esm.js.map +1 -0
  59. package/dist/components/RenameConversationModal.esm.js +157 -0
  60. package/dist/components/RenameConversationModal.esm.js.map +1 -0
  61. package/dist/components/Router.esm.js +35 -0
  62. package/dist/components/Router.esm.js.map +1 -0
  63. package/dist/components/SourcesChipModal.esm.js +124 -0
  64. package/dist/components/SourcesChipModal.esm.js.map +1 -0
  65. package/dist/components/ToolCallContent.esm.js +208 -0
  66. package/dist/components/ToolCallContent.esm.js.map +1 -0
  67. package/dist/components/Trans.esm.js +33 -0
  68. package/dist/components/Trans.esm.js.map +1 -0
  69. package/dist/components/notebooks/AddDocumentModal.esm.js +271 -0
  70. package/dist/components/notebooks/AddDocumentModal.esm.js.map +1 -0
  71. package/dist/components/notebooks/DeleteDocumentModal.esm.js +131 -0
  72. package/dist/components/notebooks/DeleteDocumentModal.esm.js.map +1 -0
  73. package/dist/components/notebooks/DeleteNotebookModal.esm.js +143 -0
  74. package/dist/components/notebooks/DeleteNotebookModal.esm.js.map +1 -0
  75. package/dist/components/notebooks/DocumentSidebar.esm.js +235 -0
  76. package/dist/components/notebooks/DocumentSidebar.esm.js.map +1 -0
  77. package/dist/components/notebooks/FileListItem.esm.js +94 -0
  78. package/dist/components/notebooks/FileListItem.esm.js.map +1 -0
  79. package/dist/components/notebooks/FileTypeIcon.esm.js +59 -0
  80. package/dist/components/notebooks/FileTypeIcon.esm.js.map +1 -0
  81. package/dist/components/notebooks/NotebookCard.esm.js +118 -0
  82. package/dist/components/notebooks/NotebookCard.esm.js.map +1 -0
  83. package/dist/components/notebooks/NotebookView.esm.js +681 -0
  84. package/dist/components/notebooks/NotebookView.esm.js.map +1 -0
  85. package/dist/components/notebooks/NotebooksTab.esm.js +71 -0
  86. package/dist/components/notebooks/NotebooksTab.esm.js.map +1 -0
  87. package/dist/components/notebooks/OverwriteConfirmModal.esm.js +142 -0
  88. package/dist/components/notebooks/OverwriteConfirmModal.esm.js.map +1 -0
  89. package/dist/components/notebooks/RenameNotebookModal.esm.js +187 -0
  90. package/dist/components/notebooks/RenameNotebookModal.esm.js.map +1 -0
  91. package/dist/components/notebooks/SidebarCollapseIcon.esm.js +50 -0
  92. package/dist/components/notebooks/SidebarCollapseIcon.esm.js.map +1 -0
  93. package/dist/components/notebooks/UploadResourceScreen.esm.js +79 -0
  94. package/dist/components/notebooks/UploadResourceScreen.esm.js.map +1 -0
  95. package/dist/const.esm.js +74 -0
  96. package/dist/const.esm.js.map +1 -0
  97. package/dist/dev.d.ts +2 -0
  98. package/dist/dev.esm.js +48 -0
  99. package/dist/dev.esm.js.map +1 -0
  100. package/dist/hooks/notebooks/useCreateNotebook.esm.js +19 -0
  101. package/dist/hooks/notebooks/useCreateNotebook.esm.js.map +1 -0
  102. package/dist/hooks/notebooks/useCreateNotebookMessage.esm.js +24 -0
  103. package/dist/hooks/notebooks/useCreateNotebookMessage.esm.js.map +1 -0
  104. package/dist/hooks/notebooks/useDeleteNotebook.esm.js +19 -0
  105. package/dist/hooks/notebooks/useDeleteNotebook.esm.js.map +1 -0
  106. package/dist/hooks/notebooks/useDocumentStatusPolling.esm.js +40 -0
  107. package/dist/hooks/notebooks/useDocumentStatusPolling.esm.js.map +1 -0
  108. package/dist/hooks/notebooks/useLightspeedNotebooksPermission.esm.js +15 -0
  109. package/dist/hooks/notebooks/useLightspeedNotebooksPermission.esm.js.map +1 -0
  110. package/dist/hooks/notebooks/useNotebookDocuments.esm.js +18 -0
  111. package/dist/hooks/notebooks/useNotebookDocuments.esm.js.map +1 -0
  112. package/dist/hooks/notebooks/useNotebookSession.esm.js +18 -0
  113. package/dist/hooks/notebooks/useNotebookSession.esm.js.map +1 -0
  114. package/dist/hooks/notebooks/useNotebookSessions.esm.js +18 -0
  115. package/dist/hooks/notebooks/useNotebookSessions.esm.js.map +1 -0
  116. package/dist/hooks/notebooks/useRenameNotebook.esm.js +19 -0
  117. package/dist/hooks/notebooks/useRenameNotebook.esm.js.map +1 -0
  118. package/dist/hooks/notebooks/useUploadDocument.esm.js +28 -0
  119. package/dist/hooks/notebooks/useUploadDocument.esm.js.map +1 -0
  120. package/dist/hooks/toolCallsCacheStore.esm.js +61 -0
  121. package/dist/hooks/toolCallsCacheStore.esm.js.map +1 -0
  122. package/dist/hooks/useAllModels.esm.js +20 -0
  123. package/dist/hooks/useAllModels.esm.js.map +1 -0
  124. package/dist/hooks/useAutoScroll.esm.js +78 -0
  125. package/dist/hooks/useAutoScroll.esm.js.map +1 -0
  126. package/dist/hooks/useBackstageUserIdentity.esm.js +14 -0
  127. package/dist/hooks/useBackstageUserIdentity.esm.js.map +1 -0
  128. package/dist/hooks/useBufferedMessages.esm.js +27 -0
  129. package/dist/hooks/useBufferedMessages.esm.js.map +1 -0
  130. package/dist/hooks/useCaptureFeedback.esm.js +21 -0
  131. package/dist/hooks/useCaptureFeedback.esm.js.map +1 -0
  132. package/dist/hooks/useConversationMessages.esm.js +544 -0
  133. package/dist/hooks/useConversationMessages.esm.js.map +1 -0
  134. package/dist/hooks/useConversations.esm.js +25 -0
  135. package/dist/hooks/useConversations.esm.js.map +1 -0
  136. package/dist/hooks/useCreateCoversationMessage.esm.js +33 -0
  137. package/dist/hooks/useCreateCoversationMessage.esm.js.map +1 -0
  138. package/dist/hooks/useDeleteConversation.esm.js +39 -0
  139. package/dist/hooks/useDeleteConversation.esm.js.map +1 -0
  140. package/dist/hooks/useDisplayModeSettings.esm.js +57 -0
  141. package/dist/hooks/useDisplayModeSettings.esm.js.map +1 -0
  142. package/dist/hooks/useFeedbackActions.esm.js +275 -0
  143. package/dist/hooks/useFeedbackActions.esm.js.map +1 -0
  144. package/dist/hooks/useFeedbackState.esm.js +93 -0
  145. package/dist/hooks/useFeedbackState.esm.js.map +1 -0
  146. package/dist/hooks/useFeedbackStatus.esm.js +14 -0
  147. package/dist/hooks/useFeedbackStatus.esm.js.map +1 -0
  148. package/dist/hooks/useIsMobile.esm.js +14 -0
  149. package/dist/hooks/useIsMobile.esm.js.map +1 -0
  150. package/dist/hooks/useLastOpenedConversation.esm.js +51 -0
  151. package/dist/hooks/useLastOpenedConversation.esm.js.map +1 -0
  152. package/dist/hooks/useLightspeedDeletePermission.esm.js +12 -0
  153. package/dist/hooks/useLightspeedDeletePermission.esm.js.map +1 -0
  154. package/dist/hooks/useLightspeedDrawerContext.esm.js +15 -0
  155. package/dist/hooks/useLightspeedDrawerContext.esm.js.map +1 -0
  156. package/dist/hooks/useLightspeedProviderState.esm.js +277 -0
  157. package/dist/hooks/useLightspeedProviderState.esm.js.map +1 -0
  158. package/dist/hooks/useLightspeedUpdatePermission.esm.js +12 -0
  159. package/dist/hooks/useLightspeedUpdatePermission.esm.js.map +1 -0
  160. package/dist/hooks/useLightspeedViewPermission.esm.js +18 -0
  161. package/dist/hooks/useLightspeedViewPermission.esm.js.map +1 -0
  162. package/dist/hooks/useNotebookConversationIds.esm.js +19 -0
  163. package/dist/hooks/useNotebookConversationIds.esm.js.map +1 -0
  164. package/dist/hooks/useNotebookWelcomePrompts.esm.js +14 -0
  165. package/dist/hooks/useNotebookWelcomePrompts.esm.js.map +1 -0
  166. package/dist/hooks/usePinnedChatsSettings.esm.js +118 -0
  167. package/dist/hooks/usePinnedChatsSettings.esm.js.map +1 -0
  168. package/dist/hooks/useQuestionValidation.esm.js +16 -0
  169. package/dist/hooks/useQuestionValidation.esm.js.map +1 -0
  170. package/dist/hooks/useRenameConversation.esm.js +44 -0
  171. package/dist/hooks/useRenameConversation.esm.js.map +1 -0
  172. package/dist/hooks/useSortSettings.esm.js +60 -0
  173. package/dist/hooks/useSortSettings.esm.js.map +1 -0
  174. package/dist/hooks/useStopConversation.esm.js +18 -0
  175. package/dist/hooks/useStopConversation.esm.js.map +1 -0
  176. package/dist/hooks/useTranslation.esm.js +7 -0
  177. package/dist/hooks/useTranslation.esm.js.map +1 -0
  178. package/dist/hooks/useWelcomePrompts.esm.js +36 -0
  179. package/dist/hooks/useWelcomePrompts.esm.js.map +1 -0
  180. package/dist/images/bot-avatar-dark.svg +4 -0
  181. package/dist/images/bot-avatar.svg +4 -0
  182. package/dist/images/permission-required.svg +319 -0
  183. package/dist/images/user-avatar.svg +4 -0
  184. package/dist/index.d.ts +113 -0
  185. package/dist/index.esm.js +137 -0
  186. package/dist/index.esm.js.map +1 -0
  187. package/dist/intelligent-assistant-fab-module.d.ts +4 -0
  188. package/dist/intelligent-assistant-fab-module.esm.js +2 -0
  189. package/dist/intelligent-assistant-fab-module.esm.js.map +1 -0
  190. package/dist/intelligent-assistant-translations-module.d.ts +4 -0
  191. package/dist/intelligent-assistant-translations-module.esm.js +2 -0
  192. package/dist/intelligent-assistant-translations-module.esm.js.map +1 -0
  193. package/dist/legacy.d.ts +75 -0
  194. package/dist/legacy.esm.js +13 -0
  195. package/dist/legacy.esm.js.map +1 -0
  196. package/dist/plugin.esm.js +84 -0
  197. package/dist/plugin.esm.js.map +1 -0
  198. package/dist/routes.esm.js +23 -0
  199. package/dist/routes.esm.js.map +1 -0
  200. package/dist/translations/de.esm.js +278 -0
  201. package/dist/translations/de.esm.js.map +1 -0
  202. package/dist/translations/es.esm.js +278 -0
  203. package/dist/translations/es.esm.js.map +1 -0
  204. package/dist/translations/fr.esm.js +278 -0
  205. package/dist/translations/fr.esm.js.map +1 -0
  206. package/dist/translations/index.esm.js +16 -0
  207. package/dist/translations/index.esm.js.map +1 -0
  208. package/dist/translations/it.esm.js +278 -0
  209. package/dist/translations/it.esm.js.map +1 -0
  210. package/dist/translations/ja.esm.js +278 -0
  211. package/dist/translations/ja.esm.js.map +1 -0
  212. package/dist/translations/ref.esm.js +315 -0
  213. package/dist/translations/ref.esm.js.map +1 -0
  214. package/dist/types.esm.js +9 -0
  215. package/dist/types.esm.js.map +1 -0
  216. package/dist/utils/attachment-utils.esm.js +30 -0
  217. package/dist/utils/attachment-utils.esm.js.map +1 -0
  218. package/dist/utils/formatToolResponseForMarkdown.esm.js +98 -0
  219. package/dist/utils/formatToolResponseForMarkdown.esm.js.map +1 -0
  220. package/dist/utils/generateClassName.esm.js +12 -0
  221. package/dist/utils/generateClassName.esm.js.map +1 -0
  222. package/dist/utils/lightspeed-chatbox-utils.esm.js +232 -0
  223. package/dist/utils/lightspeed-chatbox-utils.esm.js.map +1 -0
  224. package/dist/utils/notebook-upload-utils.esm.js +48 -0
  225. package/dist/utils/notebook-upload-utils.esm.js.map +1 -0
  226. package/dist/utils/notebooks-utils.esm.js +25 -0
  227. package/dist/utils/notebooks-utils.esm.js.map +1 -0
  228. package/dist/utils/prompt-utils.esm.js +17 -0
  229. package/dist/utils/prompt-utils.esm.js.map +1 -0
  230. package/dist/utils/queryClient.esm.js +6 -0
  231. package/dist/utils/queryClient.esm.js.map +1 -0
  232. package/dist/utils/reasoningParser.esm.js +33 -0
  233. package/dist/utils/reasoningParser.esm.js.map +1 -0
  234. package/dist/utils/toolCallMapper.esm.js +15 -0
  235. package/dist/utils/toolCallMapper.esm.js.map +1 -0
  236. package/dist/utils/user-utils.esm.js +7 -0
  237. package/dist/utils/user-utils.esm.js.map +1 -0
  238. package/package.json +182 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Router.esm.js","sources":["../../src/components/Router.tsx"],"sourcesContent":["/*\n * Copyright Red Hat, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Route, Routes } from 'react-router-dom';\n\nimport { configApiRef, useApi } from '@backstage/core-plugin-api';\n\nimport { StylesProvider as StylesProviderV4 } from '@material-ui/core/styles';\nimport { StylesProvider } from '@mui/styles';\n\nimport {\n generateClassName,\n generateClassNameV4,\n} from '../utils/generateClassName';\nimport { LightspeedPage } from './LightspeedPage';\n\n/**\n * @public\n */\nexport const Router = () => {\n const configApi = useApi(configApiRef);\n const notebooksEnabled =\n configApi.getOptionalBoolean('intelligent-assistant.notebooks.enabled') ??\n false;\n\n return (\n <StylesProvider generateClassName={generateClassName}>\n <StylesProviderV4 generateClassName={generateClassNameV4}>\n <Routes>\n <Route path=\"/\" element={<LightspeedPage />} />\n <Route\n path=\"/conversation/:conversationId\"\n element={<LightspeedPage />}\n />\n {notebooksEnabled && (\n <>\n <Route path=\"/notebooks\" element={<LightspeedPage />} />\n <Route\n path=\"/notebooks/:notebookId\"\n element={<LightspeedPage />}\n />\n </>\n )}\n </Routes>\n </StylesProviderV4>\n </StylesProvider>\n );\n};\n"],"names":["StylesProviderV4"],"mappings":";;;;;;;;AAgCO,MAAM,SAAS,MAAM;AAC1B,EAAA,MAAM,SAAA,GAAY,OAAO,YAAY,CAAA;AACrC,EAAA,MAAM,gBAAA,GACJ,SAAA,CAAU,kBAAA,CAAmB,yCAAyC,CAAA,IACtE,KAAA;AAEF,EAAA,uBACE,GAAA,CAAC,kBAAe,iBAAA,EACd,QAAA,kBAAA,GAAA,CAACA,oBAAiB,iBAAA,EAAmB,mBAAA,EACnC,+BAAC,MAAA,EAAA,EACC,QAAA,EAAA;AAAA,oBAAA,GAAA,CAAC,SAAM,IAAA,EAAK,GAAA,EAAI,OAAA,kBAAS,GAAA,CAAC,kBAAe,CAAA,EAAI,CAAA;AAAA,oBAC7C,GAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACC,IAAA,EAAK,+BAAA;AAAA,QACL,OAAA,sBAAU,cAAA,EAAA,EAAe;AAAA;AAAA,KAC3B;AAAA,IACC,oCACC,IAAA,CAAA,QAAA,EAAA,EACE,QAAA,EAAA;AAAA,sBAAA,GAAA,CAAC,SAAM,IAAA,EAAK,YAAA,EAAa,OAAA,kBAAS,GAAA,CAAC,kBAAe,CAAA,EAAI,CAAA;AAAA,sBACtD,GAAA;AAAA,QAAC,KAAA;AAAA,QAAA;AAAA,UACC,IAAA,EAAK,wBAAA;AAAA,UACL,OAAA,sBAAU,cAAA,EAAA,EAAe;AAAA;AAAA;AAC3B,KAAA,EACF;AAAA,GAAA,EAEJ,GACF,CAAA,EACF,CAAA;AAEJ;;;;"}
@@ -0,0 +1,124 @@
1
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
2
+ import { makeStyles } from '@material-ui/core';
3
+ import { Popover, Button, HelperText, HelperTextItem, List, ListItem, Tooltip } from '@patternfly/react-core';
4
+ import { LinkIcon, InfoCircleIcon } from '@patternfly/react-icons';
5
+ import { useTranslation } from '../hooks/useTranslation.esm.js';
6
+ import { FileTypeIcon } from './notebooks/FileTypeIcon.esm.js';
7
+
8
+ const POPOVER_WIDTH = "400px";
9
+ const useStyles = makeStyles((theme) => ({
10
+ sourcesPopover: {
11
+ "& .pf-v6-c-popover__title": {
12
+ alignItems: "flex-start"
13
+ },
14
+ "& .pf-v6-c-popover__title-text": {
15
+ margin: 0
16
+ },
17
+ "& .pf-v6-c-popover__header": {
18
+ paddingBlockEnd: theme.spacing(2)
19
+ },
20
+ "& .pf-v6-c-popover__body": {
21
+ paddingBlockStart: 0
22
+ }
23
+ },
24
+ chipButton: {
25
+ padding: "4px 12px",
26
+ fontSize: "0.8125rem",
27
+ fontWeight: 500,
28
+ borderRadius: 16,
29
+ backgroundColor: "transparent",
30
+ color: "var(--pf-t--global--text--color--regular, #1b1d21)",
31
+ "&:hover": {
32
+ backgroundColor: "var(--pf-t--global--background--color--secondary--default, #e0e0e0)"
33
+ },
34
+ "& .pf-v6-c-button__icon": {
35
+ color: "inherit"
36
+ }
37
+ },
38
+ helperText: {
39
+ marginBottom: theme.spacing(1.5),
40
+ color: "var(--pf-t--global--text--color--subtle, #c7c7c7)"
41
+ },
42
+ sourcesList: {
43
+ maxHeight: 320,
44
+ overflowY: "auto"
45
+ },
46
+ sourceItem: {
47
+ alignItems: "center",
48
+ "& .pf-v6-c-list__item-text": {
49
+ minWidth: 0
50
+ }
51
+ },
52
+ sourceContent: {
53
+ flex: 1,
54
+ minWidth: 0
55
+ },
56
+ sourceTitle: {
57
+ fontSize: "0.875rem",
58
+ fontWeight: 500,
59
+ overflow: "hidden",
60
+ textOverflow: "ellipsis",
61
+ whiteSpace: "nowrap"
62
+ },
63
+ sourceBody: {
64
+ fontSize: "0.8125rem",
65
+ color: "var(--pf-t--global--text--color--subtle, #c7c7c7)",
66
+ marginTop: 2,
67
+ overflow: "hidden",
68
+ textOverflow: "ellipsis",
69
+ display: "-webkit-box",
70
+ WebkitLineClamp: 2,
71
+ WebkitBoxOrient: "vertical"
72
+ }
73
+ }));
74
+ const SourcesChipModal = ({ sources }) => {
75
+ const classes = useStyles();
76
+ const { t } = useTranslation();
77
+ const count = sources.sources?.length ?? 0;
78
+ if (count === 0) return null;
79
+ return /* @__PURE__ */ jsx(
80
+ Popover,
81
+ {
82
+ className: classes.sourcesPopover,
83
+ position: "top-start",
84
+ triggerAction: "click",
85
+ "aria-label": t("sources.modal.title"),
86
+ headerContent: t("sources.modal.title"),
87
+ headerIcon: /* @__PURE__ */ jsx(LinkIcon, {}),
88
+ closeBtnAriaLabel: t("sources.popover.closeAriaLabel"),
89
+ minWidth: POPOVER_WIDTH,
90
+ maxWidth: POPOVER_WIDTH,
91
+ appendTo: () => document.body,
92
+ bodyContent: /* @__PURE__ */ jsxs(Fragment, { children: [
93
+ /* @__PURE__ */ jsx(HelperText, { className: classes.helperText, children: /* @__PURE__ */ jsx(HelperTextItem, { variant: "indeterminate", icon: /* @__PURE__ */ jsx(InfoCircleIcon, {}), children: t("sources.modal.description") }) }),
94
+ /* @__PURE__ */ jsx(
95
+ List,
96
+ {
97
+ isPlain: true,
98
+ className: classes.sourcesList,
99
+ "aria-label": t("sources.modal.title"),
100
+ children: sources.sources.map((source, index) => {
101
+ const title = source.title ?? `Source ${index + 1}`;
102
+ return /* @__PURE__ */ jsx(
103
+ ListItem,
104
+ {
105
+ className: classes.sourceItem,
106
+ icon: /* @__PURE__ */ jsx(FileTypeIcon, { fileName: title }),
107
+ children: /* @__PURE__ */ jsxs("div", { className: classes.sourceContent, children: [
108
+ /* @__PURE__ */ jsx(Tooltip, { content: title, children: /* @__PURE__ */ jsx("div", { className: classes.sourceTitle, children: title }) }),
109
+ source.body && /* @__PURE__ */ jsx("div", { className: classes.sourceBody, children: source.body })
110
+ ] })
111
+ },
112
+ `${source.title}-${index}`
113
+ );
114
+ })
115
+ }
116
+ )
117
+ ] }),
118
+ children: /* @__PURE__ */ jsx(Button, { variant: "link", icon: /* @__PURE__ */ jsx(LinkIcon, {}), className: classes.chipButton, children: t("sources.chip.label", { count }) })
119
+ }
120
+ );
121
+ };
122
+
123
+ export { SourcesChipModal };
124
+ //# sourceMappingURL=SourcesChipModal.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SourcesChipModal.esm.js","sources":["../../src/components/SourcesChipModal.tsx"],"sourcesContent":["/*\n * Copyright Red Hat, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { makeStyles } from '@material-ui/core';\nimport { SourcesCardProps } from '@patternfly/chatbot';\nimport {\n Button,\n HelperText,\n HelperTextItem,\n List,\n ListItem,\n Popover,\n Tooltip,\n} from '@patternfly/react-core';\nimport { InfoCircleIcon, LinkIcon } from '@patternfly/react-icons';\n\nimport { useTranslation } from '../hooks/useTranslation';\nimport { FileTypeIcon } from './notebooks/FileTypeIcon';\n\nconst POPOVER_WIDTH = '400px';\n\nconst useStyles = makeStyles(theme => ({\n sourcesPopover: {\n '& .pf-v6-c-popover__title': {\n alignItems: 'flex-start',\n },\n '& .pf-v6-c-popover__title-text': {\n margin: 0,\n },\n '& .pf-v6-c-popover__header': {\n paddingBlockEnd: theme.spacing(2),\n },\n '& .pf-v6-c-popover__body': {\n paddingBlockStart: 0,\n },\n },\n chipButton: {\n padding: '4px 12px',\n fontSize: '0.8125rem',\n fontWeight: 500,\n borderRadius: 16,\n backgroundColor: 'transparent',\n color: 'var(--pf-t--global--text--color--regular, #1b1d21)',\n '&:hover': {\n backgroundColor:\n 'var(--pf-t--global--background--color--secondary--default, #e0e0e0)',\n },\n '& .pf-v6-c-button__icon': {\n color: 'inherit',\n },\n },\n helperText: {\n marginBottom: theme.spacing(1.5),\n color: 'var(--pf-t--global--text--color--subtle, #c7c7c7)',\n },\n sourcesList: {\n maxHeight: 320,\n overflowY: 'auto' as const,\n },\n sourceItem: {\n alignItems: 'center',\n '& .pf-v6-c-list__item-text': {\n minWidth: 0,\n },\n },\n sourceContent: {\n flex: 1,\n minWidth: 0,\n },\n sourceTitle: {\n fontSize: '0.875rem',\n fontWeight: 500,\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n },\n sourceBody: {\n fontSize: '0.8125rem',\n color: 'var(--pf-t--global--text--color--subtle, #c7c7c7)',\n marginTop: 2,\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n display: '-webkit-box',\n WebkitLineClamp: 2,\n WebkitBoxOrient: 'vertical',\n },\n}));\n\ntype SourcesChipModalProps = {\n sources: SourcesCardProps;\n};\n\nexport const SourcesChipModal = ({ sources }: SourcesChipModalProps) => {\n const classes = useStyles();\n const { t } = useTranslation();\n\n const count = sources.sources?.length ?? 0;\n if (count === 0) return null;\n\n return (\n <Popover\n className={classes.sourcesPopover}\n position=\"top-start\"\n triggerAction=\"click\"\n aria-label={t('sources.modal.title')}\n headerContent={t('sources.modal.title')}\n headerIcon={<LinkIcon />}\n closeBtnAriaLabel={t('sources.popover.closeAriaLabel')}\n minWidth={POPOVER_WIDTH}\n maxWidth={POPOVER_WIDTH}\n appendTo={() => document.body}\n bodyContent={\n <>\n <HelperText className={classes.helperText}>\n <HelperTextItem variant=\"indeterminate\" icon={<InfoCircleIcon />}>\n {t('sources.modal.description')}\n </HelperTextItem>\n </HelperText>\n <List\n isPlain\n className={classes.sourcesList}\n aria-label={t('sources.modal.title')}\n >\n {sources.sources.map((source, index) => {\n const title = source.title ?? `Source ${index + 1}`;\n return (\n <ListItem\n key={`${source.title}-${index}`}\n className={classes.sourceItem}\n icon={<FileTypeIcon fileName={title} />}\n >\n <div className={classes.sourceContent}>\n <Tooltip content={title}>\n <div className={classes.sourceTitle}>{title}</div>\n </Tooltip>\n {source.body && (\n <div className={classes.sourceBody}>{source.body}</div>\n )}\n </div>\n </ListItem>\n );\n })}\n </List>\n </>\n }\n >\n <Button variant=\"link\" icon={<LinkIcon />} className={classes.chipButton}>\n {(t as Function)('sources.chip.label', { count })}\n </Button>\n </Popover>\n );\n};\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,208 @@
1
+ import { jsxs, jsx } from 'react/jsx-runtime';
2
+ import { makeStyles } from '@material-ui/core';
3
+ import { Message } from '@patternfly/chatbot';
4
+ import { Flex, FlexItem, Content, ContentVariants, DescriptionList, DescriptionListGroup, DescriptionListTerm, DescriptionListDescription, Label } from '@patternfly/react-core';
5
+ import { WrenchIcon } from '@patternfly/react-icons';
6
+ import { useTranslation } from '../hooks/useTranslation.esm.js';
7
+ import { formatToolResponseForMarkdown } from '../utils/formatToolResponseForMarkdown.esm.js';
8
+
9
+ const useStyles = makeStyles(() => ({
10
+ codeBlock: {
11
+ "& .pf-chatbot__message-code-block": {
12
+ border: "1px solid var(--pf-t--global--border--color--default)",
13
+ borderRadius: "var(--pf-t--global--border--radius--small)"
14
+ }
15
+ }
16
+ }));
17
+ const ToolCallContent = ({
18
+ toolCall,
19
+ role = "bot"
20
+ }) => {
21
+ const classes = useStyles();
22
+ const { t } = useTranslation();
23
+ const formatExecutionTime = (seconds) => {
24
+ if (seconds === void 0) return "";
25
+ if (seconds < 1) return `${Math.round(seconds * 1e3)}ms`;
26
+ return `${seconds.toFixed(2)}s`;
27
+ };
28
+ const getParameterKeys = () => {
29
+ if (!toolCall.arguments) return [];
30
+ return Object.keys(toolCall.arguments).filter(
31
+ (key) => key !== "server_label" && toolCall.arguments[key] !== "" && toolCall.arguments[key] !== null
32
+ );
33
+ };
34
+ const getThinkingTime = () => {
35
+ if (toolCall.startTime && toolCall.endTime) {
36
+ return Math.round((toolCall.endTime - toolCall.startTime) / 1e3);
37
+ }
38
+ return 0;
39
+ };
40
+ const thinkingTime = getThinkingTime();
41
+ const parameterKeys = getParameterKeys();
42
+ const mcpServerTitle = (() => {
43
+ const label = toolCall.arguments?.server_label;
44
+ if (typeof label === "string" && label.trim() !== "") {
45
+ return label.trim();
46
+ }
47
+ return t("toolCall.mcpServer");
48
+ })();
49
+ return /* @__PURE__ */ jsxs(
50
+ Flex,
51
+ {
52
+ direction: { default: "column" },
53
+ spaceItems: { default: "spaceItemsSm" },
54
+ children: [
55
+ thinkingTime > 0 && /* @__PURE__ */ jsx(FlexItem, { children: /* @__PURE__ */ jsx(Content, { component: ContentVariants.small, children: t("toolCall.thinking", {
56
+ seconds: String(thinkingTime)
57
+ }) }) }),
58
+ /* @__PURE__ */ jsx(FlexItem, { children: /* @__PURE__ */ jsx(Content, { component: ContentVariants.p, children: t("toolCall.summary") }) }),
59
+ /* @__PURE__ */ jsx(FlexItem, { children: /* @__PURE__ */ jsx(
60
+ "div",
61
+ {
62
+ style: {
63
+ border: "1px solid var(--pf-t--global--border--color--default)",
64
+ borderRadius: "var(--pf-t--global--border--radius--small)",
65
+ padding: "var(--pf-t--global--spacer--md)"
66
+ },
67
+ children: /* @__PURE__ */ jsxs(
68
+ Flex,
69
+ {
70
+ direction: { default: "column" },
71
+ spaceItems: { default: "spaceItemsSm" },
72
+ children: [
73
+ /* @__PURE__ */ jsxs(
74
+ FlexItem,
75
+ {
76
+ style: {
77
+ borderBottom: "1px solid var(--pf-t--global--border--color--default)",
78
+ paddingBottom: "var(--pf-t--global--spacer--sm)"
79
+ },
80
+ children: [
81
+ /* @__PURE__ */ jsxs(
82
+ Content,
83
+ {
84
+ component: ContentVariants.p,
85
+ style: { marginBlockEnd: 0 },
86
+ children: [
87
+ /* @__PURE__ */ jsx(
88
+ WrenchIcon,
89
+ {
90
+ style: {
91
+ color: "var(--pf-t--global--icon--color--brand--default)",
92
+ marginRight: "0.5em"
93
+ }
94
+ }
95
+ ),
96
+ /* @__PURE__ */ jsx("strong", { children: mcpServerTitle })
97
+ ]
98
+ }
99
+ ),
100
+ toolCall.executionTime !== void 0 && /* @__PURE__ */ jsxs(Content, { component: ContentVariants.small, children: [
101
+ t("toolCall.executionTime"),
102
+ formatExecutionTime(toolCall.executionTime)
103
+ ] })
104
+ ]
105
+ }
106
+ ),
107
+ /* @__PURE__ */ jsx(FlexItem, { children: /* @__PURE__ */ jsxs(
108
+ DescriptionList,
109
+ {
110
+ style: {
111
+ "--pf-v6-c-description-list--RowGap": "var(--pf-t--global--spacer--md)"
112
+ },
113
+ "aria-label": "Tool response",
114
+ children: [
115
+ parameterKeys.length > 0 && /* @__PURE__ */ jsxs(
116
+ DescriptionListGroup,
117
+ {
118
+ style: {
119
+ "--pf-v6-c-description-list__group--RowGap": "var(--pf-t--global--spacer--xs)"
120
+ },
121
+ children: [
122
+ /* @__PURE__ */ jsx(DescriptionListTerm, { children: t("toolCall.parameters", {
123
+ defaultValue: "Parameters"
124
+ }) || "Parameters" }),
125
+ /* @__PURE__ */ jsx(
126
+ DescriptionListDescription,
127
+ {
128
+ style: { marginInlineStart: 0 },
129
+ children: /* @__PURE__ */ jsxs(Flex, { direction: { default: "column" }, children: [
130
+ toolCall.description && /* @__PURE__ */ jsx(FlexItem, { children: /* @__PURE__ */ jsx(Content, { component: ContentVariants.small, children: toolCall.description }) }),
131
+ /* @__PURE__ */ jsx(FlexItem, { children: /* @__PURE__ */ jsx(
132
+ Flex,
133
+ {
134
+ gap: { default: "gapSm" },
135
+ flexWrap: { default: "wrap" },
136
+ children: parameterKeys.map((key) => /* @__PURE__ */ jsx(FlexItem, { children: /* @__PURE__ */ jsx(Label, { variant: "outline", color: "blue", children: key }) }, key))
137
+ }
138
+ ) })
139
+ ] })
140
+ }
141
+ )
142
+ ]
143
+ }
144
+ ),
145
+ toolCall.response && /* @__PURE__ */ jsxs(
146
+ DescriptionListGroup,
147
+ {
148
+ style: {
149
+ "--pf-v6-c-description-list__group--RowGap": "var(--pf-t--global--spacer--xs)"
150
+ },
151
+ children: [
152
+ /* @__PURE__ */ jsx(
153
+ Flex,
154
+ {
155
+ alignItems: { default: "alignItemsCenter" },
156
+ justifyContent: { default: "justifyContentSpaceBetween" },
157
+ children: /* @__PURE__ */ jsx(FlexItem, { flex: { default: "flex_1" }, children: /* @__PURE__ */ jsxs("strong", { children: [
158
+ " ",
159
+ t("toolCall.response")
160
+ ] }) })
161
+ }
162
+ ),
163
+ /* @__PURE__ */ jsx(
164
+ DescriptionListDescription,
165
+ {
166
+ style: { marginInlineStart: 0 },
167
+ children: /* @__PURE__ */ jsx(
168
+ Flex,
169
+ {
170
+ direction: { default: "column" },
171
+ spaceItems: { default: "spaceItemsXs" },
172
+ children: /* @__PURE__ */ jsx(FlexItem, { className: classes.codeBlock, children: /* @__PURE__ */ jsx(
173
+ Message,
174
+ {
175
+ content: formatToolResponseForMarkdown(
176
+ toolCall.response
177
+ ),
178
+ role,
179
+ codeBlockProps: {
180
+ isExpandable: true,
181
+ expandableSectionProps: {
182
+ truncateMaxLines: 12
183
+ }
184
+ }
185
+ }
186
+ ) })
187
+ }
188
+ )
189
+ }
190
+ )
191
+ ]
192
+ }
193
+ )
194
+ ]
195
+ }
196
+ ) })
197
+ ]
198
+ }
199
+ )
200
+ }
201
+ ) })
202
+ ]
203
+ }
204
+ );
205
+ };
206
+
207
+ export { ToolCallContent };
208
+ //# sourceMappingURL=ToolCallContent.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ToolCallContent.esm.js","sources":["../../src/components/ToolCallContent.tsx"],"sourcesContent":["/*\n * Copyright Red Hat, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { makeStyles } from '@material-ui/core';\nimport { Message } from '@patternfly/chatbot';\nimport {\n Content,\n ContentVariants,\n DescriptionList,\n DescriptionListDescription,\n DescriptionListGroup,\n DescriptionListTerm,\n Flex,\n FlexItem,\n Label,\n} from '@patternfly/react-core';\nimport { WrenchIcon } from '@patternfly/react-icons';\n\nimport { useTranslation } from '../hooks/useTranslation';\nimport { ToolCall } from '../types';\nimport { formatToolResponseForMarkdown } from '../utils/formatToolResponseForMarkdown';\n\ninterface ToolCallContentProps {\n toolCall: ToolCall;\n role?: 'user' | 'bot';\n}\n\nconst useStyles = makeStyles(() => ({\n codeBlock: {\n '& .pf-chatbot__message-code-block': {\n border: '1px solid var(--pf-t--global--border--color--default)',\n borderRadius: 'var(--pf-t--global--border--radius--small)',\n },\n },\n}));\n\n/**\n * Lightweight component for rendering tool call expandable content.\n * Used inside PatternFly's ToolCall component's expandableContent prop.\n */\nexport const ToolCallContent = ({\n toolCall,\n role = 'bot',\n}: ToolCallContentProps) => {\n const classes = useStyles();\n const { t } = useTranslation();\n\n const formatExecutionTime = (seconds?: number): string => {\n if (seconds === undefined) return '';\n if (seconds < 1) return `${Math.round(seconds * 1000)}ms`;\n return `${seconds.toFixed(2)}s`;\n };\n\n const getParameterKeys = (): string[] => {\n if (!toolCall.arguments) return [];\n return Object.keys(toolCall.arguments).filter(\n key =>\n key !== 'server_label' &&\n toolCall.arguments[key] !== '' &&\n toolCall.arguments[key] !== null,\n );\n };\n\n const getThinkingTime = (): number => {\n if (toolCall.startTime && toolCall.endTime) {\n return Math.round((toolCall.endTime - toolCall.startTime) / 1000);\n }\n return 0;\n };\n\n const thinkingTime = getThinkingTime();\n const parameterKeys = getParameterKeys();\n\n const mcpServerTitle = (() => {\n const label = toolCall.arguments?.server_label;\n if (typeof label === 'string' && label.trim() !== '') {\n return label.trim();\n }\n return t('toolCall.mcpServer');\n })();\n\n return (\n <Flex\n direction={{ default: 'column' }}\n spaceItems={{ default: 'spaceItemsSm' }}\n >\n {/* Thinking Time */}\n {thinkingTime > 0 && (\n <FlexItem>\n <Content component={ContentVariants.small}>\n {t('toolCall.thinking' as any, {\n seconds: String(thinkingTime),\n })}\n </Content>\n </FlexItem>\n )}\n\n {/* Summary */}\n <FlexItem>\n <Content component={ContentVariants.p}>{t('toolCall.summary')}</Content>\n </FlexItem>\n\n {/* Tool Header with MCP Server */}\n <FlexItem>\n <div\n style={{\n border: '1px solid var(--pf-t--global--border--color--default)',\n borderRadius: 'var(--pf-t--global--border--radius--small)',\n padding: 'var(--pf-t--global--spacer--md)',\n }}\n >\n <Flex\n direction={{ default: 'column' }}\n spaceItems={{ default: 'spaceItemsSm' }}\n >\n <FlexItem\n style={{\n borderBottom:\n '1px solid var(--pf-t--global--border--color--default)',\n paddingBottom: 'var(--pf-t--global--spacer--sm)',\n }}\n >\n <Content\n component={ContentVariants.p}\n style={{ marginBlockEnd: 0 }}\n >\n <WrenchIcon\n style={{\n color: 'var(--pf-t--global--icon--color--brand--default)',\n marginRight: '0.5em',\n }}\n />\n <strong>{mcpServerTitle}</strong>\n </Content>\n {toolCall.executionTime !== undefined && (\n <Content component={ContentVariants.small}>\n {t('toolCall.executionTime')}\n {formatExecutionTime(toolCall.executionTime)}\n </Content>\n )}\n </FlexItem>\n\n {/* Description List for Parameters and Response */}\n <FlexItem>\n <DescriptionList\n style={\n {\n '--pf-v6-c-description-list--RowGap':\n 'var(--pf-t--global--spacer--md)',\n } as any\n }\n aria-label=\"Tool response\"\n >\n {/* Parameters Section */}\n {parameterKeys.length > 0 && (\n <DescriptionListGroup\n style={\n {\n '--pf-v6-c-description-list__group--RowGap':\n 'var(--pf-t--global--spacer--xs)',\n } as any\n }\n >\n <DescriptionListTerm>\n {t('toolCall.parameters' as any, {\n defaultValue: 'Parameters',\n }) || 'Parameters'}\n </DescriptionListTerm>\n <DescriptionListDescription\n style={{ marginInlineStart: 0 }}\n >\n <Flex direction={{ default: 'column' }}>\n {toolCall.description && (\n <FlexItem>\n <Content component={ContentVariants.small}>\n {toolCall.description}\n </Content>\n </FlexItem>\n )}\n <FlexItem>\n <Flex\n gap={{ default: 'gapSm' }}\n flexWrap={{ default: 'wrap' }}\n >\n {parameterKeys.map(key => (\n <FlexItem key={key}>\n <Label variant=\"outline\" color=\"blue\">\n {key}\n </Label>\n </FlexItem>\n ))}\n </Flex>\n </FlexItem>\n </Flex>\n </DescriptionListDescription>\n </DescriptionListGroup>\n )}\n\n {/* Response Section */}\n {toolCall.response && (\n <DescriptionListGroup\n style={\n {\n '--pf-v6-c-description-list__group--RowGap':\n 'var(--pf-t--global--spacer--xs)',\n } as any\n }\n >\n {/* <DescriptionListTerm> */}\n <Flex\n alignItems={{ default: 'alignItemsCenter' }}\n justifyContent={{ default: 'justifyContentSpaceBetween' }}\n >\n <FlexItem flex={{ default: 'flex_1' }}>\n <strong> {t('toolCall.response')}</strong>\n </FlexItem>\n </Flex>\n {/* </DescriptionListTerm> */}\n <DescriptionListDescription\n style={{ marginInlineStart: 0 }}\n >\n <Flex\n direction={{ default: 'column' }}\n spaceItems={{ default: 'spaceItemsXs' }}\n >\n <FlexItem className={classes.codeBlock}>\n <Message\n content={formatToolResponseForMarkdown(\n toolCall.response,\n )}\n role={role}\n codeBlockProps={{\n isExpandable: true,\n expandableSectionProps: {\n truncateMaxLines: 12,\n },\n }}\n />\n </FlexItem>\n </Flex>\n </DescriptionListDescription>\n </DescriptionListGroup>\n )}\n </DescriptionList>\n </FlexItem>\n </Flex>\n </div>\n </FlexItem>\n </Flex>\n );\n};\n\nexport default ToolCallContent;\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ import { jsx, Fragment } from 'react/jsx-runtime';
2
+ import { cloneElement } from 'react';
3
+ import { useTranslation } from '../hooks/useTranslation.esm.js';
4
+
5
+ const Trans = ({ message, params, components }) => {
6
+ const { t } = useTranslation();
7
+ const translatedText = t(message, params || {});
8
+ if (!components) {
9
+ return /* @__PURE__ */ jsx(Fragment, { children: translatedText });
10
+ }
11
+ let result = translatedText;
12
+ const markers = {};
13
+ let markerIndex = 0;
14
+ for (const [placeholder, component] of Object.entries(components)) {
15
+ const marker = `__MARKER_${markerIndex}__`;
16
+ markers[marker] = component;
17
+ result = result.replace(new RegExp(escapeRegExp(placeholder), "g"), marker);
18
+ markerIndex++;
19
+ }
20
+ const parts = result.split(/(__MARKER_\d+__)/);
21
+ return /* @__PURE__ */ jsx(Fragment, { children: parts.map((part, index) => {
22
+ if (markers[part]) {
23
+ return cloneElement(markers[part], { key: index });
24
+ }
25
+ return part;
26
+ }) });
27
+ };
28
+ function escapeRegExp(string) {
29
+ return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
30
+ }
31
+
32
+ export { Trans };
33
+ //# sourceMappingURL=Trans.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Trans.esm.js","sources":["../../src/components/Trans.tsx"],"sourcesContent":["/*\n * Copyright Red Hat, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { cloneElement } from 'react';\n\nimport { useTranslation } from '../hooks/useTranslation';\n\ninterface TransProps {\n message: string;\n params?: Record<string, any>;\n components?: Record<string, React.ReactElement>;\n}\n\nexport const Trans = ({ message, params, components }: TransProps) => {\n const { t } = useTranslation();\n const translatedText = t(message as any, params || {});\n\n // If no components are provided, just return the text\n if (!components) {\n return <>{translatedText}</>;\n }\n\n // Simple string replacement approach - no regex, no security risks\n let result = translatedText;\n\n // Replace each placeholder with a unique marker\n const markers: Record<string, React.ReactElement> = {};\n let markerIndex = 0;\n\n for (const [placeholder, component] of Object.entries(components)) {\n const marker = `__MARKER_${markerIndex}__`;\n markers[marker] = component;\n result = result.replace(new RegExp(escapeRegExp(placeholder), 'g'), marker);\n markerIndex++;\n }\n\n // Split by markers and render components\n const parts = result.split(/(__MARKER_\\d+__)/);\n\n return (\n <>\n {parts.map((part: string, index: number) => {\n if (markers[part]) {\n return cloneElement(markers[part], { key: index });\n }\n return part;\n })}\n </>\n );\n};\n\n// Helper function to escape special regex characters\nfunction escapeRegExp(string: string): string {\n return string.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n"],"names":[],"mappings":";;;;AA2BO,MAAM,QAAQ,CAAC,EAAE,OAAA,EAAS,MAAA,EAAQ,YAAW,KAAkB;AACpE,EAAA,MAAM,EAAE,CAAA,EAAE,GAAI,cAAA,EAAe;AAC7B,EAAA,MAAM,cAAA,GAAiB,CAAA,CAAE,OAAA,EAAgB,MAAA,IAAU,EAAE,CAAA;AAGrD,EAAA,IAAI,CAAC,UAAA,EAAY;AACf,IAAA,uCAAU,QAAA,EAAA,cAAA,EAAe,CAAA;AAAA,EAC3B;AAGA,EAAA,IAAI,MAAA,GAAS,cAAA;AAGb,EAAA,MAAM,UAA8C,EAAC;AACrD,EAAA,IAAI,WAAA,GAAc,CAAA;AAElB,EAAA,KAAA,MAAW,CAAC,WAAA,EAAa,SAAS,KAAK,MAAA,CAAO,OAAA,CAAQ,UAAU,CAAA,EAAG;AACjE,IAAA,MAAM,MAAA,GAAS,YAAY,WAAW,CAAA,EAAA,CAAA;AACtC,IAAA,OAAA,CAAQ,MAAM,CAAA,GAAI,SAAA;AAClB,IAAA,MAAA,GAAS,MAAA,CAAO,QAAQ,IAAI,MAAA,CAAO,aAAa,WAAW,CAAA,EAAG,GAAG,CAAA,EAAG,MAAM,CAAA;AAC1E,IAAA,WAAA,EAAA;AAAA,EACF;AAGA,EAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,KAAA,CAAM,kBAAkB,CAAA;AAE7C,EAAA,uBACE,GAAA,CAAA,QAAA,EAAA,EACG,QAAA,EAAA,KAAA,CAAM,GAAA,CAAI,CAAC,MAAc,KAAA,KAAkB;AAC1C,IAAA,IAAI,OAAA,CAAQ,IAAI,CAAA,EAAG;AACjB,MAAA,OAAO,aAAa,OAAA,CAAQ,IAAI,GAAG,EAAE,GAAA,EAAK,OAAO,CAAA;AAAA,IACnD;AACA,IAAA,OAAO,IAAA;AAAA,EACT,CAAC,CAAA,EACH,CAAA;AAEJ;AAGA,SAAS,aAAa,MAAA,EAAwB;AAC5C,EAAA,OAAO,MAAA,CAAO,OAAA,CAAQ,qBAAA,EAAuB,MAAM,CAAA;AACrD;;;;"}