@red-hat-developer-hub/backstage-plugin-intelligent-assistant 5.0.0 → 5.0.2

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 (102) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/dist/alpha.d.ts +1 -2
  3. package/dist/components/Attachment.esm.js +14 -14
  4. package/dist/components/Attachment.esm.js.map +1 -1
  5. package/dist/components/CollapsedHistoryStrip.esm.js +46 -51
  6. package/dist/components/CollapsedHistoryStrip.esm.js.map +1 -1
  7. package/dist/components/DeleteModal.esm.js +1 -0
  8. package/dist/components/DeleteModal.esm.js.map +1 -1
  9. package/dist/components/FilePreview.esm.js +3 -2
  10. package/dist/components/FilePreview.esm.js.map +1 -1
  11. package/dist/components/LightSpeedChat.esm.js +580 -745
  12. package/dist/components/LightSpeedChat.esm.js.map +1 -1
  13. package/dist/components/LightspeedChatBox.esm.js +44 -72
  14. package/dist/components/LightspeedChatBox.esm.js.map +1 -1
  15. package/dist/components/LightspeedChatBoxHeader.esm.js +38 -34
  16. package/dist/components/LightspeedChatBoxHeader.esm.js.map +1 -1
  17. package/dist/components/LightspeedChatContainer.esm.js +6 -8
  18. package/dist/components/LightspeedChatContainer.esm.js.map +1 -1
  19. package/dist/components/LightspeedChatModelsState.esm.js +67 -73
  20. package/dist/components/LightspeedChatModelsState.esm.js.map +1 -1
  21. package/dist/components/LightspeedDrawerContext.esm.js.map +1 -1
  22. package/dist/components/LightspeedDrawerProvider.esm.js +13 -16
  23. package/dist/components/LightspeedDrawerProvider.esm.js.map +1 -1
  24. package/dist/components/LightspeedFABContent.esm.js +40 -9
  25. package/dist/components/LightspeedFABContent.esm.js.map +1 -1
  26. package/dist/components/LightspeedPage.esm.js +1 -10
  27. package/dist/components/LightspeedPage.esm.js.map +1 -1
  28. package/dist/components/McpConfigureServerModal.esm.js +79 -86
  29. package/dist/components/McpConfigureServerModal.esm.js.map +1 -1
  30. package/dist/components/McpServersSettings.esm.js +246 -212
  31. package/dist/components/McpServersSettings.esm.js.map +1 -1
  32. package/dist/components/MessageBarModelSelector.esm.js +29 -33
  33. package/dist/components/MessageBarModelSelector.esm.js.map +1 -1
  34. package/dist/components/PermissionRequiredState.esm.js +63 -63
  35. package/dist/components/PermissionRequiredState.esm.js.map +1 -1
  36. package/dist/components/RagSourceLabel.esm.js +22 -0
  37. package/dist/components/RagSourceLabel.esm.js.map +1 -0
  38. package/dist/components/RenameConversationModal.esm.js +38 -31
  39. package/dist/components/RenameConversationModal.esm.js.map +1 -1
  40. package/dist/components/Router.esm.js +4 -13
  41. package/dist/components/Router.esm.js.map +1 -1
  42. package/dist/components/SourcesChipModal.esm.js +94 -89
  43. package/dist/components/SourcesChipModal.esm.js.map +1 -1
  44. package/dist/components/ToastAlertGroup.esm.js +24 -40
  45. package/dist/components/ToastAlertGroup.esm.js.map +1 -1
  46. package/dist/components/ToolCallContent.esm.js +8 -11
  47. package/dist/components/ToolCallContent.esm.js.map +1 -1
  48. package/dist/components/notebooks/AddDocumentModal.esm.js +232 -252
  49. package/dist/components/notebooks/AddDocumentModal.esm.js.map +1 -1
  50. package/dist/components/notebooks/DeleteDocumentModal.esm.js +35 -77
  51. package/dist/components/notebooks/DeleteDocumentModal.esm.js.map +1 -1
  52. package/dist/components/notebooks/DeleteNotebookModal.esm.js +46 -81
  53. package/dist/components/notebooks/DeleteNotebookModal.esm.js.map +1 -1
  54. package/dist/components/notebooks/DocumentSidebar.esm.js +172 -196
  55. package/dist/components/notebooks/DocumentSidebar.esm.js.map +1 -1
  56. package/dist/components/notebooks/FileListItem.esm.js +69 -57
  57. package/dist/components/notebooks/FileListItem.esm.js.map +1 -1
  58. package/dist/components/notebooks/FileTypeIcon.esm.js +17 -27
  59. package/dist/components/notebooks/FileTypeIcon.esm.js.map +1 -1
  60. package/dist/components/notebooks/NotebookCard.esm.js +86 -25
  61. package/dist/components/notebooks/NotebookCard.esm.js.map +1 -1
  62. package/dist/components/notebooks/NotebookView.esm.js +367 -380
  63. package/dist/components/notebooks/NotebookView.esm.js.map +1 -1
  64. package/dist/components/notebooks/NotebooksTab.esm.js +93 -30
  65. package/dist/components/notebooks/NotebooksTab.esm.js.map +1 -1
  66. package/dist/components/notebooks/OverwriteConfirmModal.esm.js +142 -184
  67. package/dist/components/notebooks/OverwriteConfirmModal.esm.js.map +1 -1
  68. package/dist/components/notebooks/UploadResourceScreen.esm.js +58 -50
  69. package/dist/components/notebooks/UploadResourceScreen.esm.js.map +1 -1
  70. package/dist/components/notebooks/notebookDialogStyles.esm.js +33 -37
  71. package/dist/components/notebooks/notebookDialogStyles.esm.js.map +1 -1
  72. package/dist/const.esm.js +15 -2
  73. package/dist/const.esm.js.map +1 -1
  74. package/dist/hooks/useAutoScroll.esm.js +11 -11
  75. package/dist/hooks/useAutoScroll.esm.js.map +1 -1
  76. package/dist/hooks/useBufferedMessages.esm.js +5 -5
  77. package/dist/hooks/useBufferedMessages.esm.js.map +1 -1
  78. package/dist/hooks/useFeedbackActions.esm.js.map +1 -1
  79. package/dist/hooks/useIsMobile.esm.js +3 -3
  80. package/dist/hooks/useIsMobile.esm.js.map +1 -1
  81. package/dist/translations/de.esm.js +1 -2
  82. package/dist/translations/de.esm.js.map +1 -1
  83. package/dist/translations/es.esm.js +1 -2
  84. package/dist/translations/es.esm.js.map +1 -1
  85. package/dist/translations/fr.esm.js +1 -2
  86. package/dist/translations/fr.esm.js.map +1 -1
  87. package/dist/translations/it.esm.js +1 -2
  88. package/dist/translations/it.esm.js.map +1 -1
  89. package/dist/translations/ja.esm.js +1 -2
  90. package/dist/translations/ja.esm.js.map +1 -1
  91. package/dist/translations/ref.esm.js +1 -2
  92. package/dist/translations/ref.esm.js.map +1 -1
  93. package/dist/types.esm.js.map +1 -1
  94. package/dist/utils/fab-anchor-utils.esm.js +41 -0
  95. package/dist/utils/fab-anchor-utils.esm.js.map +1 -0
  96. package/dist/utils/lightspeed-chatbox-utils.esm.js +13 -6
  97. package/dist/utils/lightspeed-chatbox-utils.esm.js.map +1 -1
  98. package/dist/utils/scoped-dialog-utils.esm.js +6 -3
  99. package/dist/utils/scoped-dialog-utils.esm.js.map +1 -1
  100. package/package.json +5 -9
  101. package/dist/utils/generateClassName.esm.js +0 -12
  102. package/dist/utils/generateClassName.esm.js.map +0 -1
@@ -1,40 +1,36 @@
1
- const notebookDialogStyles = (theme) => ({
2
- dialogPaper: {
3
- borderRadius: 24,
4
- maxWidth: 578
5
- },
6
- dialogPaperCompact: {
7
- borderRadius: 12,
8
- maxWidth: "300px"
9
- },
10
- dialogTitle: {
11
- display: "flex",
12
- alignItems: "center",
13
- justifyContent: "space-between",
14
- padding: "24px 24px 16px"
15
- },
16
- dialogTitleCompact: {
17
- display: "flex",
18
- alignItems: "center",
19
- justifyContent: "space-between",
20
- padding: "16px 16px 12px !important"
21
- },
22
- titleText: {
23
- fontWeight: 500,
24
- fontSize: "1.25rem",
25
- lineHeight: "1.625rem",
26
- letterSpacing: "-0.25px"
27
- },
28
- closeButton: {
29
- color: theme.palette.text.primary
30
- },
31
- dialogContent: {
32
- padding: "0 24px 24px"
33
- },
34
- dialogContentCompact: {
35
- padding: "0 16px 16px !important"
36
- }
1
+ const notebookDialogPaperSx = (isCompact) => ({
2
+ borderRadius: isCompact ? "12px" : "24px",
3
+ maxWidth: isCompact ? 300 : 578
4
+ });
5
+ const notebookDialogTitleSx = (isCompact) => ({
6
+ display: "flex",
7
+ alignItems: "center",
8
+ justifyContent: "space-between",
9
+ p: isCompact ? "16px 16px 12px !important" : "24px 24px 16px"
10
+ });
11
+ const notebookDialogTitleTextSx = (isCompact) => ({
12
+ fontWeight: isCompact ? 600 : 500,
13
+ fontSize: isCompact ? "1.125rem" : "1.25rem",
14
+ lineHeight: isCompact ? "1.5rem" : "1.625rem",
15
+ letterSpacing: "-0.25px"
37
16
  });
17
+ const notebookDialogCloseButtonSx = {
18
+ color: "text.primary"
19
+ };
20
+ const notebookDialogContentSx = (isCompact) => ({
21
+ p: isCompact ? "0 16px 16px !important" : "0 24px 24px"
22
+ });
23
+ const notebookDialogActionsSx = (isCompact) => ({
24
+ justifyContent: "flex-start",
25
+ p: isCompact ? "12px 16px !important" : "16px 24px",
26
+ gap: 1
27
+ });
28
+ const optionalStyle = (sx) => {
29
+ if (!sx || typeof sx === "function" || Array.isArray(sx)) {
30
+ return false;
31
+ }
32
+ return sx;
33
+ };
38
34
 
39
- export { notebookDialogStyles };
35
+ export { notebookDialogActionsSx, notebookDialogCloseButtonSx, notebookDialogContentSx, notebookDialogPaperSx, notebookDialogTitleSx, notebookDialogTitleTextSx, optionalStyle };
40
36
  //# sourceMappingURL=notebookDialogStyles.esm.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"notebookDialogStyles.esm.js","sources":["../../../src/components/notebooks/notebookDialogStyles.ts"],"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 type { Theme } from '@material-ui/core/styles';\n\nexport const notebookDialogStyles = (theme: Theme) =>\n ({\n dialogPaper: {\n borderRadius: 24,\n maxWidth: 578,\n },\n dialogPaperCompact: {\n borderRadius: 12,\n maxWidth: '300px',\n },\n dialogTitle: {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n padding: '24px 24px 16px',\n },\n dialogTitleCompact: {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n padding: '16px 16px 12px !important',\n },\n titleText: {\n fontWeight: 500,\n fontSize: '1.25rem',\n lineHeight: '1.625rem',\n letterSpacing: '-0.25px',\n },\n closeButton: {\n color: theme.palette.text.primary,\n },\n dialogContent: {\n padding: '0 24px 24px',\n },\n dialogContentCompact: {\n padding: '0 16px 16px !important',\n },\n }) as const;\n"],"names":[],"mappings":"AAkBO,MAAM,oBAAA,GAAuB,CAAC,KAAA,MAClC;AAAA,EACC,WAAA,EAAa;AAAA,IACX,YAAA,EAAc,EAAA;AAAA,IACd,QAAA,EAAU;AAAA,GACZ;AAAA,EACA,kBAAA,EAAoB;AAAA,IAClB,YAAA,EAAc,EAAA;AAAA,IACd,QAAA,EAAU;AAAA,GACZ;AAAA,EACA,WAAA,EAAa;AAAA,IACX,OAAA,EAAS,MAAA;AAAA,IACT,UAAA,EAAY,QAAA;AAAA,IACZ,cAAA,EAAgB,eAAA;AAAA,IAChB,OAAA,EAAS;AAAA,GACX;AAAA,EACA,kBAAA,EAAoB;AAAA,IAClB,OAAA,EAAS,MAAA;AAAA,IACT,UAAA,EAAY,QAAA;AAAA,IACZ,cAAA,EAAgB,eAAA;AAAA,IAChB,OAAA,EAAS;AAAA,GACX;AAAA,EACA,SAAA,EAAW;AAAA,IACT,UAAA,EAAY,GAAA;AAAA,IACZ,QAAA,EAAU,SAAA;AAAA,IACV,UAAA,EAAY,UAAA;AAAA,IACZ,aAAA,EAAe;AAAA,GACjB;AAAA,EACA,WAAA,EAAa;AAAA,IACX,KAAA,EAAO,KAAA,CAAM,OAAA,CAAQ,IAAA,CAAK;AAAA,GAC5B;AAAA,EACA,aAAA,EAAe;AAAA,IACb,OAAA,EAAS;AAAA,GACX;AAAA,EACA,oBAAA,EAAsB;AAAA,IACpB,OAAA,EAAS;AAAA;AAEb,CAAA;;;;"}
1
+ {"version":3,"file":"notebookDialogStyles.esm.js","sources":["../../../src/components/notebooks/notebookDialogStyles.ts"],"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 type { SxProps, Theme } from '@mui/material/styles';\n\ntype StaticDialogSx = Exclude<\n SxProps<Theme>,\n readonly unknown[] | ((theme: Theme) => unknown)\n>;\n\nexport const notebookDialogPaperSx = (isCompact: boolean): StaticDialogSx => ({\n borderRadius: isCompact ? '12px' : '24px',\n maxWidth: isCompact ? 300 : 578,\n});\n\nexport const notebookDialogTitleSx = (isCompact: boolean): StaticDialogSx => ({\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n p: isCompact ? '16px 16px 12px !important' : '24px 24px 16px',\n});\n\nexport const notebookDialogTitleTextSx = (\n isCompact: boolean,\n): StaticDialogSx => ({\n fontWeight: isCompact ? 600 : 500,\n fontSize: isCompact ? '1.125rem' : '1.25rem',\n lineHeight: isCompact ? '1.5rem' : '1.625rem',\n letterSpacing: '-0.25px',\n});\n\nexport const notebookDialogCloseButtonSx = {\n color: 'text.primary',\n} as const;\n\nexport const notebookDialogContentSx = (\n isCompact: boolean,\n): StaticDialogSx => ({\n p: isCompact ? '0 16px 16px !important' : '0 24px 24px',\n});\n\nexport const notebookDialogActionsSx = (\n isCompact: boolean,\n): StaticDialogSx => ({\n justifyContent: 'flex-start',\n p: isCompact ? '12px 16px !important' : '16px 24px',\n gap: 1,\n});\n\n/** Narrow Dialog Paper `sx` so it can sit in an `sx={[...]}` array. */\nexport const optionalStyle = (\n sx: SxProps<Theme> | undefined,\n): StaticDialogSx | false => {\n if (!sx || typeof sx === 'function' || Array.isArray(sx)) {\n return false;\n }\n return sx as StaticDialogSx;\n};\n"],"names":[],"mappings":"AAuBO,MAAM,qBAAA,GAAwB,CAAC,SAAA,MAAwC;AAAA,EAC5E,YAAA,EAAc,YAAY,MAAA,GAAS,MAAA;AAAA,EACnC,QAAA,EAAU,YAAY,GAAA,GAAM;AAC9B,CAAA;AAEO,MAAM,qBAAA,GAAwB,CAAC,SAAA,MAAwC;AAAA,EAC5E,OAAA,EAAS,MAAA;AAAA,EACT,UAAA,EAAY,QAAA;AAAA,EACZ,cAAA,EAAgB,eAAA;AAAA,EAChB,CAAA,EAAG,YAAY,2BAAA,GAA8B;AAC/C,CAAA;AAEO,MAAM,yBAAA,GAA4B,CACvC,SAAA,MACoB;AAAA,EACpB,UAAA,EAAY,YAAY,GAAA,GAAM,GAAA;AAAA,EAC9B,QAAA,EAAU,YAAY,UAAA,GAAa,SAAA;AAAA,EACnC,UAAA,EAAY,YAAY,QAAA,GAAW,UAAA;AAAA,EACnC,aAAA,EAAe;AACjB,CAAA;AAEO,MAAM,2BAAA,GAA8B;AAAA,EACzC,KAAA,EAAO;AACT;AAEO,MAAM,uBAAA,GAA0B,CACrC,SAAA,MACoB;AAAA,EACpB,CAAA,EAAG,YAAY,wBAAA,GAA2B;AAC5C,CAAA;AAEO,MAAM,uBAAA,GAA0B,CACrC,SAAA,MACoB;AAAA,EACpB,cAAA,EAAgB,YAAA;AAAA,EAChB,CAAA,EAAG,YAAY,sBAAA,GAAyB,WAAA;AAAA,EACxC,GAAA,EAAK;AACP,CAAA;AAGO,MAAM,aAAA,GAAgB,CAC3B,EAAA,KAC2B;AAC3B,EAAA,IAAI,CAAC,MAAM,OAAO,EAAA,KAAO,cAAc,KAAA,CAAM,OAAA,CAAQ,EAAE,CAAA,EAAG;AACxD,IAAA,OAAO,KAAA;AAAA,EACT;AACA,EAAA,OAAO,EAAA;AACT;;;;"}
package/dist/const.esm.js CHANGED
@@ -67,9 +67,22 @@ const NOTEBOOK_PROMPT_KEYS = [
67
67
  const VALID_TOPIC_RESTRICTION_PROVIDER_IDS = [
68
68
  "lightspeed_question_validity-shield"
69
69
  ];
70
- const DOCKED_CONTENT_OFFSET = "calc(var(--docked-drawer-width, 500px) + 1.5em)";
70
+ const LIGHTSPEED_FAB_ELEMENT_ID = "lightspeed-fab";
71
+ const LIGHTSPEED_OVERLAY_CHATBOT_MODAL_CLASS = "ia-overlay-chatbot-modal";
72
+ const LIGHTSPEED_FAB_ANCHOR_VARS = {
73
+ insetBlockEnd: "--ia-fab-inset-block-end",
74
+ insetInlineEnd: "--ia-fab-inset-inline-end",
75
+ height: "--ia-fab-height",
76
+ overlayGap: "--ia-overlay-gap",
77
+ dockedDrawerGutter: "--ia-docked-drawer-gutter"
78
+ };
79
+ const zero = "0px";
80
+ const DOCKED_CONTENT_OFFSET = `calc(var(--docked-drawer-width, ${zero}) + var(${LIGHTSPEED_FAB_ANCHOR_VARS.dockedDrawerGutter}, ${zero}))`;
81
+ const LIGHTSPEED_OVERLAY_BOTTOM = `calc(var(${LIGHTSPEED_FAB_ANCHOR_VARS.insetBlockEnd}, ${zero}) + var(${LIGHTSPEED_FAB_ANCHOR_VARS.height}, ${zero}) + var(${LIGHTSPEED_FAB_ANCHOR_VARS.overlayGap}, ${zero}))`;
82
+ const LIGHTSPEED_OVERLAY_RIGHT = `var(${LIGHTSPEED_FAB_ANCHOR_VARS.insetInlineEnd}, ${zero})`;
83
+ const LIGHTSPEED_OVERLAY_MAX_WIDTH = `min(30rem, calc(100vw - 2 * var(${LIGHTSPEED_FAB_ANCHOR_VARS.overlayGap}, ${zero})))`;
71
84
  const LIGHTSPEED_PATH = "/intelligent-assistant";
72
85
  const LIGHTSPEED_LEGACY_PATH = "/lightspeed";
73
86
 
74
- export { DEFAULT_SAMPLE_PROMPTS, DOCKED_CONTENT_OFFSET, LIGHTSPEED_APP_DRAWER_ID, LIGHTSPEED_LEGACY_PATH, LIGHTSPEED_PATH, NOTEBOOK_ALLOWED_EXTENSIONS, NOTEBOOK_EXTENSION_TO_FILE_TYPE, NOTEBOOK_MAX_FILES, NOTEBOOK_MAX_FILE_SIZE_BYTES, NOTEBOOK_MAX_TITLE_LENGTH, NOTEBOOK_PROMPT_KEYS, RHDH_SAMPLE_PROMPTS, TEMP_CONVERSATION_ID, UNTITLED_NOTEBOOK_NAME, VALID_TOPIC_RESTRICTION_PROVIDER_IDS, supportedFileTypes };
87
+ export { DEFAULT_SAMPLE_PROMPTS, DOCKED_CONTENT_OFFSET, LIGHTSPEED_APP_DRAWER_ID, LIGHTSPEED_FAB_ANCHOR_VARS, LIGHTSPEED_FAB_ELEMENT_ID, LIGHTSPEED_LEGACY_PATH, LIGHTSPEED_OVERLAY_BOTTOM, LIGHTSPEED_OVERLAY_CHATBOT_MODAL_CLASS, LIGHTSPEED_OVERLAY_MAX_WIDTH, LIGHTSPEED_OVERLAY_RIGHT, LIGHTSPEED_PATH, NOTEBOOK_ALLOWED_EXTENSIONS, NOTEBOOK_EXTENSION_TO_FILE_TYPE, NOTEBOOK_MAX_FILES, NOTEBOOK_MAX_FILE_SIZE_BYTES, NOTEBOOK_MAX_TITLE_LENGTH, NOTEBOOK_PROMPT_KEYS, RHDH_SAMPLE_PROMPTS, TEMP_CONVERSATION_ID, UNTITLED_NOTEBOOK_NAME, VALID_TOPIC_RESTRICTION_PROVIDER_IDS, supportedFileTypes };
75
88
  //# sourceMappingURL=const.esm.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"const.esm.js","sources":["../src/const.ts"],"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 { SamplePrompts } from './types';\n\nexport const TEMP_CONVERSATION_ID = 'temp-conversation-id';\n\nexport const LIGHTSPEED_APP_DRAWER_ID = 'intelligent-assistant';\n\n// Translation keys for disclaimers\nexport const FUNCTION_DISCLAIMER_WITHOUT_QUESTION_VALIDATION_KEY =\n 'disclaimer.withoutValidation';\nexport const FUNCTION_DISCLAIMER_KEY = 'disclaimer.withValidation';\n\nconst createPrompt = (titleKey: string, messageKey: string) => {\n return { titleKey, messageKey };\n};\n\nexport const supportedFileTypes = {\n 'text/plain': ['.txt'],\n 'application/json': ['.json'],\n 'application/yaml': ['.yaml', '.yml'],\n};\n\nexport const NOTEBOOK_MAX_FILES = 10;\nexport const NOTEBOOK_MAX_FILE_SIZE_BYTES = 25 * 1024 * 1024; // 25 MB\nexport const NOTEBOOK_MAX_TITLE_LENGTH = 255;\nexport const UNTITLED_NOTEBOOK_NAME = 'Untitled Notebook';\n\nexport const NOTEBOOK_ALLOWED_EXTENSIONS: Record<string, string[]> = {\n 'text/plain': ['.txt', '.log'],\n 'text/markdown': ['.md'],\n 'application/pdf': ['.pdf'],\n 'application/json': ['.json'],\n 'application/x-yaml': ['.yaml', '.yml'],\n};\n\nexport const NOTEBOOK_EXTENSION_TO_FILE_TYPE: Record<string, string> = {\n '.txt': 'txt',\n '.md': 'md',\n '.pdf': 'pdf',\n '.json': 'json',\n '.yaml': 'yaml',\n '.yml': 'yaml',\n '.log': 'log',\n};\n\nexport const DEFAULT_SAMPLE_PROMPTS: SamplePrompts = [\n createPrompt(\n 'prompts.codeReadability.title',\n 'prompts.codeReadability.message',\n ),\n createPrompt('prompts.debugging.title', 'prompts.debugging.message'),\n createPrompt(\n 'prompts.developmentConcept.title',\n 'prompts.developmentConcept.message',\n ),\n createPrompt(\n 'prompts.codeOptimization.title',\n 'prompts.codeOptimization.message',\n ),\n createPrompt('prompts.documentation.title', 'prompts.documentation.message'),\n createPrompt('prompts.gitWorkflows.title', 'prompts.gitWorkflows.message'),\n createPrompt(\n 'prompts.testingStrategies.title',\n 'prompts.testingStrategies.message',\n ),\n createPrompt(\n 'prompts.sortingAlgorithms.title',\n 'prompts.sortingAlgorithms.message',\n ),\n createPrompt('prompts.eventDriven.title', 'prompts.eventDriven.message'),\n];\n\nexport const RHDH_SAMPLE_PROMPTS: SamplePrompts = [\n createPrompt('prompts.tekton.title', 'prompts.tekton.message'),\n createPrompt('prompts.openshift.title', 'prompts.openshift.message'),\n createPrompt('prompts.rhdh.title', 'prompts.rhdh.message'),\n];\n\nexport const NOTEBOOK_PROMPT_KEYS: string[] = [\n 'notebooks.prompts.coreConcepts.title',\n 'notebooks.prompts.vulnerabilities.title',\n 'notebooks.prompts.accessIssue.title',\n];\n\n// Topic restriction valid provider IDs\nexport const VALID_TOPIC_RESTRICTION_PROVIDER_IDS = [\n 'lightspeed_question_validity-shield',\n];\n\n// Matches app shell margin on main when ApplicationDrawer is docked (e.g. Root.tsx).\nexport const DOCKED_CONTENT_OFFSET =\n 'calc(var(--docked-drawer-width, 500px) + 1.5em)';\n\nexport const LIGHTSPEED_PATH = '/intelligent-assistant';\nexport const LIGHTSPEED_LEGACY_PATH = '/lightspeed';\n"],"names":[],"mappings":"AAkBO,MAAM,oBAAA,GAAuB;AAE7B,MAAM,wBAAA,GAA2B;AAOxC,MAAM,YAAA,GAAe,CAAC,QAAA,EAAkB,UAAA,KAAuB;AAC7D,EAAA,OAAO,EAAE,UAAU,UAAA,EAAW;AAChC,CAAA;AAEO,MAAM,kBAAA,GAAqB;AAAA,EAChC,YAAA,EAAc,CAAC,MAAM,CAAA;AAAA,EACrB,kBAAA,EAAoB,CAAC,OAAO,CAAA;AAAA,EAC5B,kBAAA,EAAoB,CAAC,OAAA,EAAS,MAAM;AACtC;AAEO,MAAM,kBAAA,GAAqB;AAC3B,MAAM,4BAAA,GAA+B,KAAK,IAAA,GAAO;AACjD,MAAM,yBAAA,GAA4B;AAClC,MAAM,sBAAA,GAAyB;AAE/B,MAAM,2BAAA,GAAwD;AAAA,EACnE,YAAA,EAAc,CAAC,MAAA,EAAQ,MAAM,CAAA;AAAA,EAC7B,eAAA,EAAiB,CAAC,KAAK,CAAA;AAAA,EACvB,iBAAA,EAAmB,CAAC,MAAM,CAAA;AAAA,EAC1B,kBAAA,EAAoB,CAAC,OAAO,CAAA;AAAA,EAC5B,oBAAA,EAAsB,CAAC,OAAA,EAAS,MAAM;AACxC;AAEO,MAAM,+BAAA,GAA0D;AAAA,EACrE,MAAA,EAAQ,KAAA;AAAA,EACR,KAAA,EAAO,IAAA;AAAA,EACP,MAAA,EAAQ,KAAA;AAAA,EACR,OAAA,EAAS,MAAA;AAAA,EACT,OAAA,EAAS,MAAA;AAAA,EACT,MAAA,EAAQ,MAAA;AAAA,EACR,MAAA,EAAQ;AACV;AAEO,MAAM,sBAAA,GAAwC;AAAA,EACnD,YAAA;AAAA,IACE,+BAAA;AAAA,IACA;AAAA,GACF;AAAA,EACA,YAAA,CAAa,2BAA2B,2BAA2B,CAAA;AAAA,EACnE,YAAA;AAAA,IACE,kCAAA;AAAA,IACA;AAAA,GACF;AAAA,EACA,YAAA;AAAA,IACE,gCAAA;AAAA,IACA;AAAA,GACF;AAAA,EACA,YAAA,CAAa,+BAA+B,+BAA+B,CAAA;AAAA,EAC3E,YAAA,CAAa,8BAA8B,8BAA8B,CAAA;AAAA,EACzE,YAAA;AAAA,IACE,iCAAA;AAAA,IACA;AAAA,GACF;AAAA,EACA,YAAA;AAAA,IACE,iCAAA;AAAA,IACA;AAAA,GACF;AAAA,EACA,YAAA,CAAa,6BAA6B,6BAA6B;AACzE;AAEO,MAAM,mBAAA,GAAqC;AAAA,EAChD,YAAA,CAAa,wBAAwB,wBAAwB,CAAA;AAAA,EAC7D,YAAA,CAAa,2BAA2B,2BAA2B,CAAA;AAAA,EACnE,YAAA,CAAa,sBAAsB,sBAAsB;AAC3D;AAEO,MAAM,oBAAA,GAAiC;AAAA,EAC5C,sCAAA;AAAA,EACA,yCAAA;AAAA,EACA;AACF;AAGO,MAAM,oCAAA,GAAuC;AAAA,EAClD;AACF;AAGO,MAAM,qBAAA,GACX;AAEK,MAAM,eAAA,GAAkB;AACxB,MAAM,sBAAA,GAAyB;;;;"}
1
+ {"version":3,"file":"const.esm.js","sources":["../src/const.ts"],"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 { SamplePrompts } from './types';\n\nexport const TEMP_CONVERSATION_ID = 'temp-conversation-id';\n\nexport const LIGHTSPEED_APP_DRAWER_ID = 'intelligent-assistant';\n\n// Translation keys for disclaimers\nexport const FUNCTION_DISCLAIMER_WITHOUT_QUESTION_VALIDATION_KEY =\n 'disclaimer.withoutValidation';\nexport const FUNCTION_DISCLAIMER_KEY = 'disclaimer';\n\nconst createPrompt = (titleKey: string, messageKey: string) => {\n return { titleKey, messageKey };\n};\n\nexport const supportedFileTypes = {\n 'text/plain': ['.txt'],\n 'application/json': ['.json'],\n 'application/yaml': ['.yaml', '.yml'],\n};\n\nexport const NOTEBOOK_MAX_FILES = 10;\nexport const NOTEBOOK_MAX_FILE_SIZE_BYTES = 25 * 1024 * 1024; // 25 MB\nexport const NOTEBOOK_MAX_TITLE_LENGTH = 255;\nexport const UNTITLED_NOTEBOOK_NAME = 'Untitled Notebook';\n\nexport const NOTEBOOK_ALLOWED_EXTENSIONS: Record<string, string[]> = {\n 'text/plain': ['.txt', '.log'],\n 'text/markdown': ['.md'],\n 'application/pdf': ['.pdf'],\n 'application/json': ['.json'],\n 'application/x-yaml': ['.yaml', '.yml'],\n};\n\nexport const NOTEBOOK_EXTENSION_TO_FILE_TYPE: Record<string, string> = {\n '.txt': 'txt',\n '.md': 'md',\n '.pdf': 'pdf',\n '.json': 'json',\n '.yaml': 'yaml',\n '.yml': 'yaml',\n '.log': 'log',\n};\n\nexport const DEFAULT_SAMPLE_PROMPTS: SamplePrompts = [\n createPrompt(\n 'prompts.codeReadability.title',\n 'prompts.codeReadability.message',\n ),\n createPrompt('prompts.debugging.title', 'prompts.debugging.message'),\n createPrompt(\n 'prompts.developmentConcept.title',\n 'prompts.developmentConcept.message',\n ),\n createPrompt(\n 'prompts.codeOptimization.title',\n 'prompts.codeOptimization.message',\n ),\n createPrompt('prompts.documentation.title', 'prompts.documentation.message'),\n createPrompt('prompts.gitWorkflows.title', 'prompts.gitWorkflows.message'),\n createPrompt(\n 'prompts.testingStrategies.title',\n 'prompts.testingStrategies.message',\n ),\n createPrompt(\n 'prompts.sortingAlgorithms.title',\n 'prompts.sortingAlgorithms.message',\n ),\n createPrompt('prompts.eventDriven.title', 'prompts.eventDriven.message'),\n];\n\nexport const RHDH_SAMPLE_PROMPTS: SamplePrompts = [\n createPrompt('prompts.tekton.title', 'prompts.tekton.message'),\n createPrompt('prompts.openshift.title', 'prompts.openshift.message'),\n createPrompt('prompts.rhdh.title', 'prompts.rhdh.message'),\n];\n\nexport const NOTEBOOK_PROMPT_KEYS: string[] = [\n 'notebooks.prompts.coreConcepts.title',\n 'notebooks.prompts.vulnerabilities.title',\n 'notebooks.prompts.accessIssue.title',\n];\n\n// Topic restriction valid provider IDs\nexport const VALID_TOPIC_RESTRICTION_PROVIDER_IDS = [\n 'lightspeed_question_validity-shield',\n];\n\nexport const LIGHTSPEED_FAB_ELEMENT_ID = 'lightspeed-fab';\nexport const LIGHTSPEED_OVERLAY_CHATBOT_MODAL_CLASS =\n 'ia-overlay-chatbot-modal';\n\n/** CSS variables published by LightspeedFABContent single source for overlay layout. */\nexport const LIGHTSPEED_FAB_ANCHOR_VARS = {\n insetBlockEnd: '--ia-fab-inset-block-end',\n insetInlineEnd: '--ia-fab-inset-inline-end',\n height: '--ia-fab-height',\n overlayGap: '--ia-overlay-gap',\n dockedDrawerGutter: '--ia-docked-drawer-gutter',\n} as const;\n\nconst zero = '0px';\n\n/** Shift FAB/overlay left when the app drawer is docked (drawer width + theme gutter). */\nexport const DOCKED_CONTENT_OFFSET = `calc(var(--docked-drawer-width, ${zero}) + var(${LIGHTSPEED_FAB_ANCHOR_VARS.dockedDrawerGutter}, ${zero}))`;\n\n/** Overlay bottom: measured FAB bottom inset + FAB height + theme gap. */\nexport const LIGHTSPEED_OVERLAY_BOTTOM = `calc(var(${LIGHTSPEED_FAB_ANCHOR_VARS.insetBlockEnd}, ${zero}) + var(${LIGHTSPEED_FAB_ANCHOR_VARS.height}, ${zero}) + var(${LIGHTSPEED_FAB_ANCHOR_VARS.overlayGap}, ${zero}))`;\n\n/** Overlay right: measured FAB right inset (tracks docked margin via getBoundingClientRect). */\nexport const LIGHTSPEED_OVERLAY_RIGHT = `var(${LIGHTSPEED_FAB_ANCHOR_VARS.insetInlineEnd}, ${zero})`;\n\n/** Overlay max width: PatternFly default capped by viewport minus theme gutters. */\nexport const LIGHTSPEED_OVERLAY_MAX_WIDTH = `min(30rem, calc(100vw - 2 * var(${LIGHTSPEED_FAB_ANCHOR_VARS.overlayGap}, ${zero})))`;\n\nexport const LIGHTSPEED_PATH = '/intelligent-assistant';\nexport const LIGHTSPEED_LEGACY_PATH = '/lightspeed';\n"],"names":[],"mappings":"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"}
@@ -1,12 +1,12 @@
1
- import React from 'react';
1
+ import { useState, useRef, useCallback, useEffect } from 'react';
2
2
 
3
3
  const useAutoScroll = (containerRef, options = {}) => {
4
4
  const { deltaUp = 10, deltaDown = 60, delay = 200 } = options;
5
- const [autoScroll, setAutoScroll] = React.useState(true);
6
- const lastScrollTop = React.useRef(0);
7
- const manualScrollInterrupted = React.useRef(false);
8
- const debounceTimeout = React.useRef(null);
9
- const onScroll = React.useCallback(() => {
5
+ const [autoScroll, setAutoScroll] = useState(true);
6
+ const lastScrollTop = useRef(0);
7
+ const manualScrollInterrupted = useRef(false);
8
+ const debounceTimeout = useRef(null);
9
+ const onScroll = useCallback(() => {
10
10
  const container = containerRef.current;
11
11
  if (!container) return;
12
12
  const currentScrollTop = container.scrollTop;
@@ -27,7 +27,7 @@ const useAutoScroll = (containerRef, options = {}) => {
27
27
  }
28
28
  lastScrollTop.current = currentScrollTop;
29
29
  }, [containerRef, deltaUp, deltaDown, delay]);
30
- React.useEffect(() => {
30
+ useEffect(() => {
31
31
  const container = containerRef.current;
32
32
  if (!container) {
33
33
  return void 0;
@@ -38,15 +38,15 @@ const useAutoScroll = (containerRef, options = {}) => {
38
38
  if (debounceTimeout.current) clearTimeout(debounceTimeout.current);
39
39
  };
40
40
  }, [onScroll, containerRef]);
41
- const resumeAutoScroll = React.useCallback(() => {
41
+ const resumeAutoScroll = useCallback(() => {
42
42
  manualScrollInterrupted.current = false;
43
43
  setAutoScroll(true);
44
44
  }, []);
45
- const stopAutoScroll = React.useCallback(() => {
45
+ const stopAutoScroll = useCallback(() => {
46
46
  manualScrollInterrupted.current = true;
47
47
  setAutoScroll(false);
48
48
  }, []);
49
- const scrollToTop = React.useCallback(() => {
49
+ const scrollToTop = useCallback(() => {
50
50
  stopAutoScroll();
51
51
  const container = containerRef.current;
52
52
  if (!container) return;
@@ -55,7 +55,7 @@ const useAutoScroll = (containerRef, options = {}) => {
55
55
  behavior: "smooth"
56
56
  });
57
57
  }, [stopAutoScroll, containerRef]);
58
- const scrollToBottom = React.useCallback(() => {
58
+ const scrollToBottom = useCallback(() => {
59
59
  const container = containerRef.current;
60
60
  if (container) {
61
61
  container.scrollTo({
@@ -1 +1 @@
1
- {"version":3,"file":"useAutoScroll.esm.js","sources":["../../src/hooks/useAutoScroll.ts"],"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 */\nimport React from 'react';\n\ninterface useAutoScrollOptions {\n deltaUp?: number;\n deltaDown?: number;\n delay?: number;\n}\n\nexport const useAutoScroll = (\n containerRef: React.RefObject<HTMLElement>,\n options: useAutoScrollOptions = {},\n) => {\n const { deltaUp = 10, deltaDown = 60, delay = 200 } = options;\n\n const [autoScroll, setAutoScroll] = React.useState(true);\n const lastScrollTop = React.useRef(0);\n const manualScrollInterrupted = React.useRef(false);\n const debounceTimeout = React.useRef<NodeJS.Timeout | null>(null);\n\n const onScroll = React.useCallback(() => {\n const container = containerRef.current;\n if (!container) return;\n\n const currentScrollTop = container.scrollTop;\n const isScrollingDown = currentScrollTop > lastScrollTop.current;\n\n const distanceFromBottom =\n container.scrollHeight - container.scrollTop - container.clientHeight;\n\n const delta = isScrollingDown ? deltaDown : deltaUp;\n const isAtBottom = distanceFromBottom <= delta;\n\n if (debounceTimeout.current) clearTimeout(debounceTimeout.current);\n\n if (isAtBottom && manualScrollInterrupted.current && isScrollingDown) {\n debounceTimeout.current = setTimeout(() => {\n manualScrollInterrupted.current = false;\n setAutoScroll(true);\n }, delay);\n }\n\n if (!isAtBottom && !manualScrollInterrupted.current) {\n manualScrollInterrupted.current = true;\n setAutoScroll(false);\n }\n\n lastScrollTop.current = currentScrollTop;\n }, [containerRef, deltaUp, deltaDown, delay]);\n\n React.useEffect(() => {\n const container = containerRef.current;\n if (!container) {\n return undefined;\n }\n\n container.addEventListener('scroll', onScroll, { passive: true });\n return () => {\n container.removeEventListener('scroll', onScroll);\n if (debounceTimeout.current) clearTimeout(debounceTimeout.current);\n };\n }, [onScroll, containerRef]);\n\n const resumeAutoScroll = React.useCallback(() => {\n manualScrollInterrupted.current = false;\n setAutoScroll(true);\n }, []);\n\n const stopAutoScroll = React.useCallback(() => {\n manualScrollInterrupted.current = true;\n setAutoScroll(false);\n }, []);\n\n const scrollToTop = React.useCallback(() => {\n stopAutoScroll();\n const container = containerRef.current;\n if (!container) return;\n\n container.scrollTo({\n top: 0,\n behavior: 'smooth',\n });\n }, [stopAutoScroll, containerRef]);\n\n const scrollToBottom = React.useCallback(() => {\n const container = containerRef.current;\n if (container) {\n container.scrollTo({\n top: container.scrollHeight,\n behavior: 'smooth',\n });\n }\n resumeAutoScroll();\n }, [resumeAutoScroll, containerRef]);\n\n return {\n autoScroll,\n resumeAutoScroll,\n stopAutoScroll,\n scrollToBottom,\n scrollToTop,\n };\n};\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"useAutoScroll.esm.js","sources":["../../src/hooks/useAutoScroll.ts"],"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 { RefObject, useCallback, useEffect, useRef, useState } from 'react';\n\ninterface useAutoScrollOptions {\n deltaUp?: number;\n deltaDown?: number;\n delay?: number;\n}\n\nexport const useAutoScroll = (\n containerRef: RefObject<HTMLElement>,\n options: useAutoScrollOptions = {},\n) => {\n const { deltaUp = 10, deltaDown = 60, delay = 200 } = options;\n\n const [autoScroll, setAutoScroll] = useState(true);\n const lastScrollTop = useRef(0);\n const manualScrollInterrupted = useRef(false);\n const debounceTimeout = useRef<NodeJS.Timeout | null>(null);\n\n const onScroll = useCallback(() => {\n const container = containerRef.current;\n if (!container) return;\n\n const currentScrollTop = container.scrollTop;\n const isScrollingDown = currentScrollTop > lastScrollTop.current;\n\n const distanceFromBottom =\n container.scrollHeight - container.scrollTop - container.clientHeight;\n\n const delta = isScrollingDown ? deltaDown : deltaUp;\n const isAtBottom = distanceFromBottom <= delta;\n\n if (debounceTimeout.current) clearTimeout(debounceTimeout.current);\n\n if (isAtBottom && manualScrollInterrupted.current && isScrollingDown) {\n debounceTimeout.current = setTimeout(() => {\n manualScrollInterrupted.current = false;\n setAutoScroll(true);\n }, delay);\n }\n\n if (!isAtBottom && !manualScrollInterrupted.current) {\n manualScrollInterrupted.current = true;\n setAutoScroll(false);\n }\n\n lastScrollTop.current = currentScrollTop;\n }, [containerRef, deltaUp, deltaDown, delay]);\n\n useEffect(() => {\n const container = containerRef.current;\n if (!container) {\n return undefined;\n }\n\n container.addEventListener('scroll', onScroll, { passive: true });\n return () => {\n container.removeEventListener('scroll', onScroll);\n if (debounceTimeout.current) clearTimeout(debounceTimeout.current);\n };\n }, [onScroll, containerRef]);\n\n const resumeAutoScroll = useCallback(() => {\n manualScrollInterrupted.current = false;\n setAutoScroll(true);\n }, []);\n\n const stopAutoScroll = useCallback(() => {\n manualScrollInterrupted.current = true;\n setAutoScroll(false);\n }, []);\n\n const scrollToTop = useCallback(() => {\n stopAutoScroll();\n const container = containerRef.current;\n if (!container) return;\n\n container.scrollTo({\n top: 0,\n behavior: 'smooth',\n });\n }, [stopAutoScroll, containerRef]);\n\n const scrollToBottom = useCallback(() => {\n const container = containerRef.current;\n if (container) {\n container.scrollTo({\n top: container.scrollHeight,\n behavior: 'smooth',\n });\n }\n resumeAutoScroll();\n }, [resumeAutoScroll, containerRef]);\n\n return {\n autoScroll,\n resumeAutoScroll,\n stopAutoScroll,\n scrollToBottom,\n scrollToTop,\n };\n};\n"],"names":[],"mappings":"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"}
@@ -1,10 +1,10 @@
1
- import React from 'react';
1
+ import { useState, useRef, useEffect } from 'react';
2
2
 
3
3
  const useBufferedMessages = (messages, interval = 30) => {
4
- const [bufferedMessages, setBufferedMessages] = React.useState(messages);
5
- const lastUpdateTime = React.useRef(0);
6
- const animationFrame = React.useRef(null);
7
- React.useEffect(() => {
4
+ const [bufferedMessages, setBufferedMessages] = useState(messages);
5
+ const lastUpdateTime = useRef(0);
6
+ const animationFrame = useRef(null);
7
+ useEffect(() => {
8
8
  const now = Date.now();
9
9
  const update = () => {
10
10
  setBufferedMessages(messages);
@@ -1 +1 @@
1
- {"version":3,"file":"useBufferedMessages.esm.js","sources":["../../src/hooks/useBufferedMessages.ts"],"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 */\nimport React from 'react';\n\nexport const useBufferedMessages = <T>(messages: T[], interval = 30): T[] => {\n const [bufferedMessages, setBufferedMessages] = React.useState(messages);\n const lastUpdateTime = React.useRef(0);\n const animationFrame = React.useRef<number | null>(null);\n\n React.useEffect(() => {\n const now = Date.now();\n\n const update = () => {\n setBufferedMessages(messages);\n lastUpdateTime.current = now;\n };\n\n if (now - lastUpdateTime.current > interval) {\n update();\n } else {\n if (animationFrame.current) cancelAnimationFrame(animationFrame.current);\n animationFrame.current = requestAnimationFrame(update);\n }\n\n return () => {\n if (animationFrame.current) cancelAnimationFrame(animationFrame.current);\n };\n }, [messages, interval]);\n\n return bufferedMessages;\n};\n"],"names":[],"mappings":";;AAiBO,MAAM,mBAAA,GAAsB,CAAI,QAAA,EAAe,QAAA,GAAW,EAAA,KAAY;AAC3E,EAAA,MAAM,CAAC,gBAAA,EAAkB,mBAAmB,CAAA,GAAI,KAAA,CAAM,SAAS,QAAQ,CAAA;AACvE,EAAA,MAAM,cAAA,GAAiB,KAAA,CAAM,MAAA,CAAO,CAAC,CAAA;AACrC,EAAA,MAAM,cAAA,GAAiB,KAAA,CAAM,MAAA,CAAsB,IAAI,CAAA;AAEvD,EAAA,KAAA,CAAM,UAAU,MAAM;AACpB,IAAA,MAAM,GAAA,GAAM,KAAK,GAAA,EAAI;AAErB,IAAA,MAAM,SAAS,MAAM;AACnB,MAAA,mBAAA,CAAoB,QAAQ,CAAA;AAC5B,MAAA,cAAA,CAAe,OAAA,GAAU,GAAA;AAAA,IAC3B,CAAA;AAEA,IAAA,IAAI,GAAA,GAAM,cAAA,CAAe,OAAA,GAAU,QAAA,EAAU;AAC3C,MAAA,MAAA,EAAO;AAAA,IACT,CAAA,MAAO;AACL,MAAA,IAAI,cAAA,CAAe,OAAA,EAAS,oBAAA,CAAqB,cAAA,CAAe,OAAO,CAAA;AACvE,MAAA,cAAA,CAAe,OAAA,GAAU,sBAAsB,MAAM,CAAA;AAAA,IACvD;AAEA,IAAA,OAAO,MAAM;AACX,MAAA,IAAI,cAAA,CAAe,OAAA,EAAS,oBAAA,CAAqB,cAAA,CAAe,OAAO,CAAA;AAAA,IACzE,CAAA;AAAA,EACF,CAAA,EAAG,CAAC,QAAA,EAAU,QAAQ,CAAC,CAAA;AAEvB,EAAA,OAAO,gBAAA;AACT;;;;"}
1
+ {"version":3,"file":"useBufferedMessages.esm.js","sources":["../../src/hooks/useBufferedMessages.ts"],"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 { useEffect, useRef, useState } from 'react';\n\nexport const useBufferedMessages = <T>(messages: T[], interval = 30): T[] => {\n const [bufferedMessages, setBufferedMessages] = useState(messages);\n const lastUpdateTime = useRef(0);\n const animationFrame = useRef<number | null>(null);\n\n useEffect(() => {\n const now = Date.now();\n\n const update = () => {\n setBufferedMessages(messages);\n lastUpdateTime.current = now;\n };\n\n if (now - lastUpdateTime.current > interval) {\n update();\n } else {\n if (animationFrame.current) cancelAnimationFrame(animationFrame.current);\n animationFrame.current = requestAnimationFrame(update);\n }\n\n return () => {\n if (animationFrame.current) cancelAnimationFrame(animationFrame.current);\n };\n }, [messages, interval]);\n\n return bufferedMessages;\n};\n"],"names":[],"mappings":";;AAkBO,MAAM,mBAAA,GAAsB,CAAI,QAAA,EAAe,QAAA,GAAW,EAAA,KAAY;AAC3E,EAAA,MAAM,CAAC,gBAAA,EAAkB,mBAAmB,CAAA,GAAI,SAAS,QAAQ,CAAA;AACjE,EAAA,MAAM,cAAA,GAAiB,OAAO,CAAC,CAAA;AAC/B,EAAA,MAAM,cAAA,GAAiB,OAAsB,IAAI,CAAA;AAEjD,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,MAAM,GAAA,GAAM,KAAK,GAAA,EAAI;AAErB,IAAA,MAAM,SAAS,MAAM;AACnB,MAAA,mBAAA,CAAoB,QAAQ,CAAA;AAC5B,MAAA,cAAA,CAAe,OAAA,GAAU,GAAA;AAAA,IAC3B,CAAA;AAEA,IAAA,IAAI,GAAA,GAAM,cAAA,CAAe,OAAA,GAAU,QAAA,EAAU;AAC3C,MAAA,MAAA,EAAO;AAAA,IACT,CAAA,MAAO;AACL,MAAA,IAAI,cAAA,CAAe,OAAA,EAAS,oBAAA,CAAqB,cAAA,CAAe,OAAO,CAAA;AACvE,MAAA,cAAA,CAAe,OAAA,GAAU,sBAAsB,MAAM,CAAA;AAAA,IACvD;AAEA,IAAA,OAAO,MAAM;AACX,MAAA,IAAI,cAAA,CAAe,OAAA,EAAS,oBAAA,CAAqB,cAAA,CAAe,OAAO,CAAA;AAAA,IACzE,CAAA;AAAA,EACF,CAAA,EAAG,CAAC,QAAA,EAAU,QAAQ,CAAC,CAAA;AAEvB,EAAA,OAAO,gBAAA;AACT;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"useFeedbackActions.esm.js","sources":["../../src/hooks/useFeedbackActions.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 */\nimport { useCallback, useEffect, useMemo, useRef } from 'react';\n\nimport { MessageProps } from '@patternfly/chatbot';\nimport { UserFeedbackProps } from '@patternfly/chatbot/dist/cjs/Message/UserFeedback/UserFeedback';\nimport { UserFeedbackCompleteProps } from '@patternfly/chatbot/dist/cjs/Message/UserFeedback/UserFeedbackComplete';\n\nimport { useCaptureFeedback } from '../hooks/useCaptureFeedback';\nimport { CaptureFeedback } from '../types';\nimport { Sentiment, useFeedbackState } from './useFeedbackState';\nimport { useFeedbackStatus } from './useFeedbackStatus';\nimport { useTranslation } from './useTranslation';\n\nexport const useFeedbackActions = <T extends MessageProps>(\n messages: T[],\n conversationId: string,\n isStreaming: boolean,\n): T[] => {\n const copyButtonRef = useRef<HTMLButtonElement>(null);\n const speakingButtonRef = useRef<HTMLButtonElement>(null);\n const currentSpeakingIdRef = useRef<string | null>(null);\n\n const { data: feedbackEnabled } = useFeedbackStatus();\n const { state, ...dispatch } = useFeedbackState();\n const { mutateAsync: captureFeedback } = useCaptureFeedback();\n const { t } = useTranslation();\n\n const createQuickResponses = useMemo(\n () => ({\n positive: [\n { id: '1', content: t('feedback.quickResponses.positive.helpful') },\n {\n id: '2',\n content: t('feedback.quickResponses.positive.easyToUnderstand'),\n },\n {\n id: '3',\n content: t('feedback.quickResponses.positive.resolvedIssue'),\n },\n ],\n negative: [\n { id: '1', content: t('feedback.quickResponses.negative.didntAnswer') },\n {\n id: '2',\n content: t('feedback.quickResponses.negative.hardToUnderstand'),\n },\n { id: '3', content: t('feedback.quickResponses.negative.notHelpful') },\n ],\n }),\n [t],\n );\n\n const getFeedbackForm = useCallback(\n (messageId: string, sentiment: 'positive' | 'negative') => ({\n key: `feedback-${sentiment}`,\n id: `feedback-${sentiment}-${messageId}`,\n hasTextArea: true,\n title: t('feedback.form.title'),\n textAreaPlaceholder: t('feedback.form.textAreaPlaceholder'),\n submitWord: t('feedback.form.submitWord'),\n quickResponses: createQuickResponses[sentiment],\n onSubmit: (\n quickResponse: string | undefined = '0',\n additionalFeedback: string | undefined,\n ) => {\n const quickIndex = Number(quickResponse) - 1;\n const quickText =\n quickResponse !== '0'\n ? createQuickResponses[sentiment]?.[quickIndex]?.content\n : undefined;\n\n let user_feedback = '';\n\n if (quickText && additionalFeedback) {\n user_feedback = `${quickText}\\nAdditional feedback: ${additionalFeedback}`;\n } else if (quickText) {\n user_feedback = quickText;\n } else if (additionalFeedback) {\n user_feedback = additionalFeedback;\n }\n\n const botAnswerId = Number(messageId.split('-').pop());\n const userQuestionId = botAnswerId - 1;\n\n const payload: CaptureFeedback = {\n conversation_id: conversationId,\n user_feedback,\n sentiment: sentiment === 'positive' ? 1 : -1,\n user_question: messages[userQuestionId].content || '',\n llm_response: messages[botAnswerId].content || '',\n };\n\n captureFeedback(payload).then(() => {\n dispatch.hideFeedbackForm(messageId, sentiment);\n dispatch.showCompletionForm(messageId, sentiment);\n dispatch.updateButtonState(messageId, {\n sentiment: sentiment,\n feedbackSubmitted: true,\n });\n\n setTimeout(() => {\n dispatch.hideCompletionForm(messageId, sentiment);\n }, 1000);\n });\n },\n\n // eslint-disable-next-line no-console\n onClose: () => {\n dispatch.hideFeedbackForm(messageId, sentiment);\n dispatch.resetButtonState(messageId);\n dispatch.updateButtonState(messageId, { sentiment: undefined });\n },\n focusOnLoad: true,\n }),\n [\n captureFeedback,\n conversationId,\n dispatch,\n messages,\n createQuickResponses,\n t,\n ],\n );\n\n const feedbackForms = useCallback(\n (messageId: string): { [key in Sentiment]: UserFeedbackProps } => ({\n positive: getFeedbackForm(messageId, 'positive'),\n negative: getFeedbackForm(messageId, 'negative'),\n }),\n [getFeedbackForm],\n );\n\n const getUserFeedbackComplete = useCallback(\n (\n messageId: string,\n sentiment: Sentiment,\n ): UserFeedbackCompleteProps | undefined => {\n const isVisible = state[messageId]?.completionForm?.[sentiment];\n if (!isVisible) return undefined;\n\n return {\n id: `feebback-completion-${sentiment}-${messageId}`,\n title: t('feedback.completion.title'),\n body: t('feedback.completion.body'),\n onClose: () => {\n dispatch.hideCompletionForm(messageId, sentiment);\n dispatch.resetButtonState(messageId);\n },\n };\n },\n [state, dispatch, t],\n );\n\n const scrollToFeedbackForm = useCallback(\n (messageId: string, sentiment: Sentiment) => {\n setTimeout(() => {\n const el = document.getElementById(\n `feedback-${sentiment}-${messageId}`,\n );\n if (el) {\n el.scrollIntoView({ behavior: 'auto', block: 'start' });\n el.focus();\n }\n }, 0);\n },\n [],\n );\n\n const speakMessage = useCallback(\n (messageId: string, content: string) => {\n if (window.speechSynthesis.speaking || window.speechSynthesis.pending) {\n window.speechSynthesis.cancel();\n\n if (\n currentSpeakingIdRef.current &&\n currentSpeakingIdRef.current !== messageId\n ) {\n dispatch.updateButtonState(currentSpeakingIdRef.current, {\n isSpeaking: false,\n });\n }\n }\n\n // Track the current SpeakingId\n currentSpeakingIdRef.current = messageId;\n\n const utterance = new SpeechSynthesisUtterance(content);\n\n utterance.onstart = () => {\n dispatch.updateButtonState(messageId, { isSpeaking: true });\n };\n\n utterance.onend = () => {\n dispatch.updateButtonState(messageId, { isSpeaking: false });\n currentSpeakingIdRef.current = null;\n };\n\n utterance.onerror = () => {\n dispatch.updateButtonState(messageId, { isSpeaking: false });\n currentSpeakingIdRef.current = null;\n };\n\n window.speechSynthesis.speak(utterance);\n },\n [dispatch],\n );\n\n const cancelSpeaking = useCallback(\n (messageId?: string) => {\n window.speechSynthesis.cancel();\n\n currentSpeakingIdRef.current = null;\n\n if (messageId) {\n // Cancel just this one message\n dispatch.updateButtonState(messageId, { isSpeaking: false });\n } else {\n // Cancel all messages\n Object.keys(state).forEach(id => {\n if (state[id].buttonState?.isSpeaking) {\n dispatch.updateButtonState(id, { isSpeaking: false });\n }\n });\n }\n setTimeout(() => {\n const el = document.getElementById(`listen-${messageId}`);\n if (el) {\n el.blur();\n }\n }, 10);\n },\n [state, dispatch],\n );\n\n useEffect(() => {\n return () => {\n // Stop any ongoing speech when component unmounts\n cancelSpeaking();\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [conversationId]);\n\n return useMemo(() => {\n return feedbackEnabled\n ? messages.map((message, index) => {\n if (\n message.role === 'user' ||\n (isStreaming && messages.length - 1 === index)\n )\n return message;\n\n const messageId = `${conversationId}-${message.role}-${index}`;\n const { sentiment, copied, isSpeaking } =\n state[messageId]?.buttonState || {};\n const showFeedbackForm = state[messageId]?.feedbackForm?.[sentiment];\n const userFeedbackForm =\n showFeedbackForm && feedbackForms(messageId)[sentiment];\n\n const userFeedbackComplete = getUserFeedbackComplete(\n messageId,\n sentiment,\n );\n\n const createSentimentAction = (selected: Sentiment) => ({\n isClicked: sentiment === selected,\n onClick: () => {\n if (sentiment !== selected) {\n dispatch.toggleFeedbackForm(messageId, selected);\n dispatch.updateButtonState(messageId, { sentiment: selected });\n scrollToFeedbackForm(messageId, sentiment);\n }\n },\n tooltipContent:\n selected === 'positive'\n ? t('feedback.tooltips.goodResponse')\n : t('feedback.tooltips.badResponse'),\n 'aria-expanded': sentiment === selected,\n 'aria-controls': showFeedbackForm\n ? `feedback-${sentiment}-${messageId}`\n : `feebback-completion-${sentiment}-${messageId}`,\n });\n\n const copyAction = {\n isClicked: copied,\n ref: copyButtonRef,\n tooltipContent: copied\n ? t('feedback.tooltips.copied')\n : t('feedback.tooltips.copy'),\n onClick: async () => {\n await window.navigator.clipboard.writeText(\n message.content as string,\n );\n dispatch.updateButtonState(messageId, {\n copied: true,\n });\n\n setTimeout(() => {\n dispatch.updateButtonState(messageId, { copied: false });\n copyButtonRef?.current?.blur();\n }, 1000);\n },\n };\n\n const listenAction = {\n isClicked: isSpeaking,\n ref: speakingButtonRef,\n id: `listen-${messageId}`,\n tooltipContent: isSpeaking\n ? t('feedback.tooltips.listening')\n : t('feedback.tooltips.listen'),\n onClick: () => {\n const isCurrentlySpeaking =\n state[messageId]?.buttonState?.isSpeaking;\n\n if (isCurrentlySpeaking) {\n // Stop if it's already speaking this message\n cancelSpeaking(messageId);\n } else {\n cancelSpeaking();\n speakMessage(messageId, message.content as string);\n }\n },\n };\n\n return {\n ...message,\n userFeedbackForm,\n userFeedbackComplete,\n actions: {\n positive: createSentimentAction('positive'),\n negative: createSentimentAction('negative'),\n copy: copyAction,\n listen: listenAction,\n },\n };\n })\n : messages;\n }, [\n t,\n conversationId,\n messages,\n state,\n dispatch,\n isStreaming,\n speakMessage,\n feedbackForms,\n cancelSpeaking,\n feedbackEnabled,\n getUserFeedbackComplete,\n scrollToFeedbackForm,\n ]);\n};\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"useFeedbackActions.esm.js","sources":["../../src/hooks/useFeedbackActions.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 */\nimport { useCallback, useEffect, useMemo, useRef } from 'react';\n\nimport {\n MessageProps,\n UserFeedbackCompleteProps,\n UserFeedbackProps,\n} from '@patternfly/chatbot';\n\nimport { useCaptureFeedback } from '../hooks/useCaptureFeedback';\nimport { CaptureFeedback } from '../types';\nimport { Sentiment, useFeedbackState } from './useFeedbackState';\nimport { useFeedbackStatus } from './useFeedbackStatus';\nimport { useTranslation } from './useTranslation';\n\nexport const useFeedbackActions = <T extends MessageProps>(\n messages: T[],\n conversationId: string,\n isStreaming: boolean,\n): T[] => {\n const copyButtonRef = useRef<HTMLButtonElement>(null);\n const speakingButtonRef = useRef<HTMLButtonElement>(null);\n const currentSpeakingIdRef = useRef<string | null>(null);\n\n const { data: feedbackEnabled } = useFeedbackStatus();\n const { state, ...dispatch } = useFeedbackState();\n const { mutateAsync: captureFeedback } = useCaptureFeedback();\n const { t } = useTranslation();\n\n const createQuickResponses = useMemo(\n () => ({\n positive: [\n { id: '1', content: t('feedback.quickResponses.positive.helpful') },\n {\n id: '2',\n content: t('feedback.quickResponses.positive.easyToUnderstand'),\n },\n {\n id: '3',\n content: t('feedback.quickResponses.positive.resolvedIssue'),\n },\n ],\n negative: [\n { id: '1', content: t('feedback.quickResponses.negative.didntAnswer') },\n {\n id: '2',\n content: t('feedback.quickResponses.negative.hardToUnderstand'),\n },\n { id: '3', content: t('feedback.quickResponses.negative.notHelpful') },\n ],\n }),\n [t],\n );\n\n const getFeedbackForm = useCallback(\n (messageId: string, sentiment: 'positive' | 'negative') => ({\n key: `feedback-${sentiment}`,\n id: `feedback-${sentiment}-${messageId}`,\n hasTextArea: true,\n title: t('feedback.form.title'),\n textAreaPlaceholder: t('feedback.form.textAreaPlaceholder'),\n submitWord: t('feedback.form.submitWord'),\n quickResponses: createQuickResponses[sentiment],\n onSubmit: (\n quickResponse: string | undefined = '0',\n additionalFeedback: string | undefined,\n ) => {\n const quickIndex = Number(quickResponse) - 1;\n const quickText =\n quickResponse !== '0'\n ? createQuickResponses[sentiment]?.[quickIndex]?.content\n : undefined;\n\n let user_feedback = '';\n\n if (quickText && additionalFeedback) {\n user_feedback = `${quickText}\\nAdditional feedback: ${additionalFeedback}`;\n } else if (quickText) {\n user_feedback = quickText;\n } else if (additionalFeedback) {\n user_feedback = additionalFeedback;\n }\n\n const botAnswerId = Number(messageId.split('-').pop());\n const userQuestionId = botAnswerId - 1;\n\n const payload: CaptureFeedback = {\n conversation_id: conversationId,\n user_feedback,\n sentiment: sentiment === 'positive' ? 1 : -1,\n user_question: messages[userQuestionId].content || '',\n llm_response: messages[botAnswerId].content || '',\n };\n\n captureFeedback(payload).then(() => {\n dispatch.hideFeedbackForm(messageId, sentiment);\n dispatch.showCompletionForm(messageId, sentiment);\n dispatch.updateButtonState(messageId, {\n sentiment: sentiment,\n feedbackSubmitted: true,\n });\n\n setTimeout(() => {\n dispatch.hideCompletionForm(messageId, sentiment);\n }, 1000);\n });\n },\n\n // eslint-disable-next-line no-console\n onClose: () => {\n dispatch.hideFeedbackForm(messageId, sentiment);\n dispatch.resetButtonState(messageId);\n dispatch.updateButtonState(messageId, { sentiment: undefined });\n },\n focusOnLoad: true,\n }),\n [\n captureFeedback,\n conversationId,\n dispatch,\n messages,\n createQuickResponses,\n t,\n ],\n );\n\n const feedbackForms = useCallback(\n (messageId: string): { [key in Sentiment]: UserFeedbackProps } => ({\n positive: getFeedbackForm(messageId, 'positive'),\n negative: getFeedbackForm(messageId, 'negative'),\n }),\n [getFeedbackForm],\n );\n\n const getUserFeedbackComplete = useCallback(\n (\n messageId: string,\n sentiment: Sentiment,\n ): UserFeedbackCompleteProps | undefined => {\n const isVisible = state[messageId]?.completionForm?.[sentiment];\n if (!isVisible) return undefined;\n\n return {\n id: `feebback-completion-${sentiment}-${messageId}`,\n title: t('feedback.completion.title'),\n body: t('feedback.completion.body'),\n onClose: () => {\n dispatch.hideCompletionForm(messageId, sentiment);\n dispatch.resetButtonState(messageId);\n },\n };\n },\n [state, dispatch, t],\n );\n\n const scrollToFeedbackForm = useCallback(\n (messageId: string, sentiment: Sentiment) => {\n setTimeout(() => {\n const el = document.getElementById(\n `feedback-${sentiment}-${messageId}`,\n );\n if (el) {\n el.scrollIntoView({ behavior: 'auto', block: 'start' });\n el.focus();\n }\n }, 0);\n },\n [],\n );\n\n const speakMessage = useCallback(\n (messageId: string, content: string) => {\n if (window.speechSynthesis.speaking || window.speechSynthesis.pending) {\n window.speechSynthesis.cancel();\n\n if (\n currentSpeakingIdRef.current &&\n currentSpeakingIdRef.current !== messageId\n ) {\n dispatch.updateButtonState(currentSpeakingIdRef.current, {\n isSpeaking: false,\n });\n }\n }\n\n // Track the current SpeakingId\n currentSpeakingIdRef.current = messageId;\n\n const utterance = new SpeechSynthesisUtterance(content);\n\n utterance.onstart = () => {\n dispatch.updateButtonState(messageId, { isSpeaking: true });\n };\n\n utterance.onend = () => {\n dispatch.updateButtonState(messageId, { isSpeaking: false });\n currentSpeakingIdRef.current = null;\n };\n\n utterance.onerror = () => {\n dispatch.updateButtonState(messageId, { isSpeaking: false });\n currentSpeakingIdRef.current = null;\n };\n\n window.speechSynthesis.speak(utterance);\n },\n [dispatch],\n );\n\n const cancelSpeaking = useCallback(\n (messageId?: string) => {\n window.speechSynthesis.cancel();\n\n currentSpeakingIdRef.current = null;\n\n if (messageId) {\n // Cancel just this one message\n dispatch.updateButtonState(messageId, { isSpeaking: false });\n } else {\n // Cancel all messages\n Object.keys(state).forEach(id => {\n if (state[id].buttonState?.isSpeaking) {\n dispatch.updateButtonState(id, { isSpeaking: false });\n }\n });\n }\n setTimeout(() => {\n const el = document.getElementById(`listen-${messageId}`);\n if (el) {\n el.blur();\n }\n }, 10);\n },\n [state, dispatch],\n );\n\n useEffect(() => {\n return () => {\n // Stop any ongoing speech when component unmounts\n cancelSpeaking();\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [conversationId]);\n\n return useMemo(() => {\n return feedbackEnabled\n ? messages.map((message, index) => {\n if (\n message.role === 'user' ||\n (isStreaming && messages.length - 1 === index)\n )\n return message;\n\n const messageId = `${conversationId}-${message.role}-${index}`;\n const { sentiment, copied, isSpeaking } =\n state[messageId]?.buttonState || {};\n const showFeedbackForm = state[messageId]?.feedbackForm?.[sentiment];\n const userFeedbackForm =\n showFeedbackForm && feedbackForms(messageId)[sentiment];\n\n const userFeedbackComplete = getUserFeedbackComplete(\n messageId,\n sentiment,\n );\n\n const createSentimentAction = (selected: Sentiment) => ({\n isClicked: sentiment === selected,\n onClick: () => {\n if (sentiment !== selected) {\n dispatch.toggleFeedbackForm(messageId, selected);\n dispatch.updateButtonState(messageId, { sentiment: selected });\n scrollToFeedbackForm(messageId, sentiment);\n }\n },\n tooltipContent:\n selected === 'positive'\n ? t('feedback.tooltips.goodResponse')\n : t('feedback.tooltips.badResponse'),\n 'aria-expanded': sentiment === selected,\n 'aria-controls': showFeedbackForm\n ? `feedback-${sentiment}-${messageId}`\n : `feebback-completion-${sentiment}-${messageId}`,\n });\n\n const copyAction = {\n isClicked: copied,\n ref: copyButtonRef,\n tooltipContent: copied\n ? t('feedback.tooltips.copied')\n : t('feedback.tooltips.copy'),\n onClick: async () => {\n await window.navigator.clipboard.writeText(\n message.content as string,\n );\n dispatch.updateButtonState(messageId, {\n copied: true,\n });\n\n setTimeout(() => {\n dispatch.updateButtonState(messageId, { copied: false });\n copyButtonRef?.current?.blur();\n }, 1000);\n },\n };\n\n const listenAction = {\n isClicked: isSpeaking,\n ref: speakingButtonRef,\n id: `listen-${messageId}`,\n tooltipContent: isSpeaking\n ? t('feedback.tooltips.listening')\n : t('feedback.tooltips.listen'),\n onClick: () => {\n const isCurrentlySpeaking =\n state[messageId]?.buttonState?.isSpeaking;\n\n if (isCurrentlySpeaking) {\n // Stop if it's already speaking this message\n cancelSpeaking(messageId);\n } else {\n cancelSpeaking();\n speakMessage(messageId, message.content as string);\n }\n },\n };\n\n return {\n ...message,\n userFeedbackForm,\n userFeedbackComplete,\n actions: {\n positive: createSentimentAction('positive'),\n negative: createSentimentAction('negative'),\n copy: copyAction,\n listen: listenAction,\n },\n };\n })\n : messages;\n }, [\n t,\n conversationId,\n messages,\n state,\n dispatch,\n isStreaming,\n speakMessage,\n feedbackForms,\n cancelSpeaking,\n feedbackEnabled,\n getUserFeedbackComplete,\n scrollToFeedbackForm,\n ]);\n};\n"],"names":[],"mappings":";;;;;;AA6BO,MAAM,kBAAA,GAAqB,CAChC,QAAA,EACA,cAAA,EACA,WAAA,KACQ;AACR,EAAA,MAAM,aAAA,GAAgB,OAA0B,IAAI,CAAA;AACpD,EAAA,MAAM,iBAAA,GAAoB,OAA0B,IAAI,CAAA;AACxD,EAAA,MAAM,oBAAA,GAAuB,OAAsB,IAAI,CAAA;AAEvD,EAAA,MAAM,EAAE,IAAA,EAAM,eAAA,EAAgB,GAAI,iBAAA,EAAkB;AACpD,EAAA,MAAM,EAAE,KAAA,EAAO,GAAG,QAAA,KAAa,gBAAA,EAAiB;AAChD,EAAA,MAAM,EAAE,WAAA,EAAa,eAAA,EAAgB,GAAI,kBAAA,EAAmB;AAC5D,EAAA,MAAM,EAAE,CAAA,EAAE,GAAI,cAAA,EAAe;AAE7B,EAAA,MAAM,oBAAA,GAAuB,OAAA;AAAA,IAC3B,OAAO;AAAA,MACL,QAAA,EAAU;AAAA,QACR,EAAE,EAAA,EAAI,GAAA,EAAK,OAAA,EAAS,CAAA,CAAE,0CAA0C,CAAA,EAAE;AAAA,QAClE;AAAA,UACE,EAAA,EAAI,GAAA;AAAA,UACJ,OAAA,EAAS,EAAE,mDAAmD;AAAA,SAChE;AAAA,QACA;AAAA,UACE,EAAA,EAAI,GAAA;AAAA,UACJ,OAAA,EAAS,EAAE,gDAAgD;AAAA;AAC7D,OACF;AAAA,MACA,QAAA,EAAU;AAAA,QACR,EAAE,EAAA,EAAI,GAAA,EAAK,OAAA,EAAS,CAAA,CAAE,8CAA8C,CAAA,EAAE;AAAA,QACtE;AAAA,UACE,EAAA,EAAI,GAAA;AAAA,UACJ,OAAA,EAAS,EAAE,mDAAmD;AAAA,SAChE;AAAA,QACA,EAAE,EAAA,EAAI,GAAA,EAAK,OAAA,EAAS,CAAA,CAAE,6CAA6C,CAAA;AAAE;AACvE,KACF,CAAA;AAAA,IACA,CAAC,CAAC;AAAA,GACJ;AAEA,EAAA,MAAM,eAAA,GAAkB,WAAA;AAAA,IACtB,CAAC,WAAmB,SAAA,MAAwC;AAAA,MAC1D,GAAA,EAAK,YAAY,SAAS,CAAA,CAAA;AAAA,MAC1B,EAAA,EAAI,CAAA,SAAA,EAAY,SAAS,CAAA,CAAA,EAAI,SAAS,CAAA,CAAA;AAAA,MACtC,WAAA,EAAa,IAAA;AAAA,MACb,KAAA,EAAO,EAAE,qBAAqB,CAAA;AAAA,MAC9B,mBAAA,EAAqB,EAAE,mCAAmC,CAAA;AAAA,MAC1D,UAAA,EAAY,EAAE,0BAA0B,CAAA;AAAA,MACxC,cAAA,EAAgB,qBAAqB,SAAS,CAAA;AAAA,MAC9C,QAAA,EAAU,CACR,aAAA,GAAoC,GAAA,EACpC,kBAAA,KACG;AACH,QAAA,MAAM,UAAA,GAAa,MAAA,CAAO,aAAa,CAAA,GAAI,CAAA;AAC3C,QAAA,MAAM,SAAA,GACJ,kBAAkB,GAAA,GACd,oBAAA,CAAqB,SAAS,CAAA,GAAI,UAAU,GAAG,OAAA,GAC/C,MAAA;AAEN,QAAA,IAAI,aAAA,GAAgB,EAAA;AAEpB,QAAA,IAAI,aAAa,kBAAA,EAAoB;AACnC,UAAA,aAAA,GAAgB,GAAG,SAAS;AAAA,qBAAA,EAA0B,kBAAkB,CAAA,CAAA;AAAA,QAC1E,WAAW,SAAA,EAAW;AACpB,UAAA,aAAA,GAAgB,SAAA;AAAA,QAClB,WAAW,kBAAA,EAAoB;AAC7B,UAAA,aAAA,GAAgB,kBAAA;AAAA,QAClB;AAEA,QAAA,MAAM,cAAc,MAAA,CAAO,SAAA,CAAU,MAAM,GAAG,CAAA,CAAE,KAAK,CAAA;AACrD,QAAA,MAAM,iBAAiB,WAAA,GAAc,CAAA;AAErC,QAAA,MAAM,OAAA,GAA2B;AAAA,UAC/B,eAAA,EAAiB,cAAA;AAAA,UACjB,aAAA;AAAA,UACA,SAAA,EAAW,SAAA,KAAc,UAAA,GAAa,CAAA,GAAI,EAAA;AAAA,UAC1C,aAAA,EAAe,QAAA,CAAS,cAAc,CAAA,CAAE,OAAA,IAAW,EAAA;AAAA,UACnD,YAAA,EAAc,QAAA,CAAS,WAAW,CAAA,CAAE,OAAA,IAAW;AAAA,SACjD;AAEA,QAAA,eAAA,CAAgB,OAAO,CAAA,CAAE,IAAA,CAAK,MAAM;AAClC,UAAA,QAAA,CAAS,gBAAA,CAAiB,WAAW,SAAS,CAAA;AAC9C,UAAA,QAAA,CAAS,kBAAA,CAAmB,WAAW,SAAS,CAAA;AAChD,UAAA,QAAA,CAAS,kBAAkB,SAAA,EAAW;AAAA,YACpC,SAAA;AAAA,YACA,iBAAA,EAAmB;AAAA,WACpB,CAAA;AAED,UAAA,UAAA,CAAW,MAAM;AACf,YAAA,QAAA,CAAS,kBAAA,CAAmB,WAAW,SAAS,CAAA;AAAA,UAClD,GAAG,GAAI,CAAA;AAAA,QACT,CAAC,CAAA;AAAA,MACH,CAAA;AAAA;AAAA,MAGA,SAAS,MAAM;AACb,QAAA,QAAA,CAAS,gBAAA,CAAiB,WAAW,SAAS,CAAA;AAC9C,QAAA,QAAA,CAAS,iBAAiB,SAAS,CAAA;AACnC,QAAA,QAAA,CAAS,iBAAA,CAAkB,SAAA,EAAW,EAAE,SAAA,EAAW,QAAW,CAAA;AAAA,MAChE,CAAA;AAAA,MACA,WAAA,EAAa;AAAA,KACf,CAAA;AAAA,IACA;AAAA,MACE,eAAA;AAAA,MACA,cAAA;AAAA,MACA,QAAA;AAAA,MACA,QAAA;AAAA,MACA,oBAAA;AAAA,MACA;AAAA;AACF,GACF;AAEA,EAAA,MAAM,aAAA,GAAgB,WAAA;AAAA,IACpB,CAAC,SAAA,MAAkE;AAAA,MACjE,QAAA,EAAU,eAAA,CAAgB,SAAA,EAAW,UAAU,CAAA;AAAA,MAC/C,QAAA,EAAU,eAAA,CAAgB,SAAA,EAAW,UAAU;AAAA,KACjD,CAAA;AAAA,IACA,CAAC,eAAe;AAAA,GAClB;AAEA,EAAA,MAAM,uBAAA,GAA0B,WAAA;AAAA,IAC9B,CACE,WACA,SAAA,KAC0C;AAC1C,MAAA,MAAM,SAAA,GAAY,KAAA,CAAM,SAAS,CAAA,EAAG,iBAAiB,SAAS,CAAA;AAC9D,MAAA,IAAI,CAAC,WAAW,OAAO,MAAA;AAEvB,MAAA,OAAO;AAAA,QACL,EAAA,EAAI,CAAA,oBAAA,EAAuB,SAAS,CAAA,CAAA,EAAI,SAAS,CAAA,CAAA;AAAA,QACjD,KAAA,EAAO,EAAE,2BAA2B,CAAA;AAAA,QACpC,IAAA,EAAM,EAAE,0BAA0B,CAAA;AAAA,QAClC,SAAS,MAAM;AACb,UAAA,QAAA,CAAS,kBAAA,CAAmB,WAAW,SAAS,CAAA;AAChD,UAAA,QAAA,CAAS,iBAAiB,SAAS,CAAA;AAAA,QACrC;AAAA,OACF;AAAA,IACF,CAAA;AAAA,IACA,CAAC,KAAA,EAAO,QAAA,EAAU,CAAC;AAAA,GACrB;AAEA,EAAA,MAAM,oBAAA,GAAuB,WAAA;AAAA,IAC3B,CAAC,WAAmB,SAAA,KAAyB;AAC3C,MAAA,UAAA,CAAW,MAAM;AACf,QAAA,MAAM,KAAK,QAAA,CAAS,cAAA;AAAA,UAClB,CAAA,SAAA,EAAY,SAAS,CAAA,CAAA,EAAI,SAAS,CAAA;AAAA,SACpC;AACA,QAAA,IAAI,EAAA,EAAI;AACN,UAAA,EAAA,CAAG,eAAe,EAAE,QAAA,EAAU,MAAA,EAAQ,KAAA,EAAO,SAAS,CAAA;AACtD,UAAA,EAAA,CAAG,KAAA,EAAM;AAAA,QACX;AAAA,MACF,GAAG,CAAC,CAAA;AAAA,IACN,CAAA;AAAA,IACA;AAAC,GACH;AAEA,EAAA,MAAM,YAAA,GAAe,WAAA;AAAA,IACnB,CAAC,WAAmB,OAAA,KAAoB;AACtC,MAAA,IAAI,MAAA,CAAO,eAAA,CAAgB,QAAA,IAAY,MAAA,CAAO,gBAAgB,OAAA,EAAS;AACrE,QAAA,MAAA,CAAO,gBAAgB,MAAA,EAAO;AAE9B,QAAA,IACE,oBAAA,CAAqB,OAAA,IACrB,oBAAA,CAAqB,OAAA,KAAY,SAAA,EACjC;AACA,UAAA,QAAA,CAAS,iBAAA,CAAkB,qBAAqB,OAAA,EAAS;AAAA,YACvD,UAAA,EAAY;AAAA,WACb,CAAA;AAAA,QACH;AAAA,MACF;AAGA,MAAA,oBAAA,CAAqB,OAAA,GAAU,SAAA;AAE/B,MAAA,MAAM,SAAA,GAAY,IAAI,wBAAA,CAAyB,OAAO,CAAA;AAEtD,MAAA,SAAA,CAAU,UAAU,MAAM;AACxB,QAAA,QAAA,CAAS,iBAAA,CAAkB,SAAA,EAAW,EAAE,UAAA,EAAY,MAAM,CAAA;AAAA,MAC5D,CAAA;AAEA,MAAA,SAAA,CAAU,QAAQ,MAAM;AACtB,QAAA,QAAA,CAAS,iBAAA,CAAkB,SAAA,EAAW,EAAE,UAAA,EAAY,OAAO,CAAA;AAC3D,QAAA,oBAAA,CAAqB,OAAA,GAAU,IAAA;AAAA,MACjC,CAAA;AAEA,MAAA,SAAA,CAAU,UAAU,MAAM;AACxB,QAAA,QAAA,CAAS,iBAAA,CAAkB,SAAA,EAAW,EAAE,UAAA,EAAY,OAAO,CAAA;AAC3D,QAAA,oBAAA,CAAqB,OAAA,GAAU,IAAA;AAAA,MACjC,CAAA;AAEA,MAAA,MAAA,CAAO,eAAA,CAAgB,MAAM,SAAS,CAAA;AAAA,IACxC,CAAA;AAAA,IACA,CAAC,QAAQ;AAAA,GACX;AAEA,EAAA,MAAM,cAAA,GAAiB,WAAA;AAAA,IACrB,CAAC,SAAA,KAAuB;AACtB,MAAA,MAAA,CAAO,gBAAgB,MAAA,EAAO;AAE9B,MAAA,oBAAA,CAAqB,OAAA,GAAU,IAAA;AAE/B,MAAA,IAAI,SAAA,EAAW;AAEb,QAAA,QAAA,CAAS,iBAAA,CAAkB,SAAA,EAAW,EAAE,UAAA,EAAY,OAAO,CAAA;AAAA,MAC7D,CAAA,MAAO;AAEL,QAAA,MAAA,CAAO,IAAA,CAAK,KAAK,CAAA,CAAE,OAAA,CAAQ,CAAA,EAAA,KAAM;AAC/B,UAAA,IAAI,KAAA,CAAM,EAAE,CAAA,CAAE,WAAA,EAAa,UAAA,EAAY;AACrC,YAAA,QAAA,CAAS,iBAAA,CAAkB,EAAA,EAAI,EAAE,UAAA,EAAY,OAAO,CAAA;AAAA,UACtD;AAAA,QACF,CAAC,CAAA;AAAA,MACH;AACA,MAAA,UAAA,CAAW,MAAM;AACf,QAAA,MAAM,EAAA,GAAK,QAAA,CAAS,cAAA,CAAe,CAAA,OAAA,EAAU,SAAS,CAAA,CAAE,CAAA;AACxD,QAAA,IAAI,EAAA,EAAI;AACN,UAAA,EAAA,CAAG,IAAA,EAAK;AAAA,QACV;AAAA,MACF,GAAG,EAAE,CAAA;AAAA,IACP,CAAA;AAAA,IACA,CAAC,OAAO,QAAQ;AAAA,GAClB;AAEA,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,OAAO,MAAM;AAEX,MAAA,cAAA,EAAe;AAAA,IACjB,CAAA;AAAA,EAEF,CAAA,EAAG,CAAC,cAAc,CAAC,CAAA;AAEnB,EAAA,OAAO,QAAQ,MAAM;AACnB,IAAA,OAAO,eAAA,GACH,QAAA,CAAS,GAAA,CAAI,CAAC,SAAS,KAAA,KAAU;AAC/B,MAAA,IACE,QAAQ,IAAA,KAAS,MAAA,IAChB,WAAA,IAAe,QAAA,CAAS,SAAS,CAAA,KAAM,KAAA;AAExC,QAAA,OAAO,OAAA;AAET,MAAA,MAAM,YAAY,CAAA,EAAG,cAAc,IAAI,OAAA,CAAQ,IAAI,IAAI,KAAK,CAAA,CAAA;AAC5D,MAAA,MAAM,EAAE,WAAW,MAAA,EAAQ,UAAA,KACzB,KAAA,CAAM,SAAS,CAAA,EAAG,WAAA,IAAe,EAAC;AACpC,MAAA,MAAM,gBAAA,GAAmB,KAAA,CAAM,SAAS,CAAA,EAAG,eAAe,SAAS,CAAA;AACnE,MAAA,MAAM,gBAAA,GACJ,gBAAA,IAAoB,aAAA,CAAc,SAAS,EAAE,SAAS,CAAA;AAExD,MAAA,MAAM,oBAAA,GAAuB,uBAAA;AAAA,QAC3B,SAAA;AAAA,QACA;AAAA,OACF;AAEA,MAAA,MAAM,qBAAA,GAAwB,CAAC,QAAA,MAAyB;AAAA,QACtD,WAAW,SAAA,KAAc,QAAA;AAAA,QACzB,SAAS,MAAM;AACb,UAAA,IAAI,cAAc,QAAA,EAAU;AAC1B,YAAA,QAAA,CAAS,kBAAA,CAAmB,WAAW,QAAQ,CAAA;AAC/C,YAAA,QAAA,CAAS,iBAAA,CAAkB,SAAA,EAAW,EAAE,SAAA,EAAW,UAAU,CAAA;AAC7D,YAAA,oBAAA,CAAqB,WAAW,SAAS,CAAA;AAAA,UAC3C;AAAA,QACF,CAAA;AAAA,QACA,gBACE,QAAA,KAAa,UAAA,GACT,EAAE,gCAAgC,CAAA,GAClC,EAAE,+BAA+B,CAAA;AAAA,QACvC,iBAAiB,SAAA,KAAc,QAAA;AAAA,QAC/B,eAAA,EAAiB,gBAAA,GACb,CAAA,SAAA,EAAY,SAAS,CAAA,CAAA,EAAI,SAAS,CAAA,CAAA,GAClC,CAAA,oBAAA,EAAuB,SAAS,CAAA,CAAA,EAAI,SAAS,CAAA;AAAA,OACnD,CAAA;AAEA,MAAA,MAAM,UAAA,GAAa;AAAA,QACjB,SAAA,EAAW,MAAA;AAAA,QACX,GAAA,EAAK,aAAA;AAAA,QACL,gBAAgB,MAAA,GACZ,CAAA,CAAE,0BAA0B,CAAA,GAC5B,EAAE,wBAAwB,CAAA;AAAA,QAC9B,SAAS,YAAY;AACnB,UAAA,MAAM,MAAA,CAAO,UAAU,SAAA,CAAU,SAAA;AAAA,YAC/B,OAAA,CAAQ;AAAA,WACV;AACA,UAAA,QAAA,CAAS,kBAAkB,SAAA,EAAW;AAAA,YACpC,MAAA,EAAQ;AAAA,WACT,CAAA;AAED,UAAA,UAAA,CAAW,MAAM;AACf,YAAA,QAAA,CAAS,iBAAA,CAAkB,SAAA,EAAW,EAAE,MAAA,EAAQ,OAAO,CAAA;AACvD,YAAA,aAAA,EAAe,SAAS,IAAA,EAAK;AAAA,UAC/B,GAAG,GAAI,CAAA;AAAA,QACT;AAAA,OACF;AAEA,MAAA,MAAM,YAAA,GAAe;AAAA,QACnB,SAAA,EAAW,UAAA;AAAA,QACX,GAAA,EAAK,iBAAA;AAAA,QACL,EAAA,EAAI,UAAU,SAAS,CAAA,CAAA;AAAA,QACvB,gBAAgB,UAAA,GACZ,CAAA,CAAE,6BAA6B,CAAA,GAC/B,EAAE,0BAA0B,CAAA;AAAA,QAChC,SAAS,MAAM;AACb,UAAA,MAAM,mBAAA,GACJ,KAAA,CAAM,SAAS,CAAA,EAAG,WAAA,EAAa,UAAA;AAEjC,UAAA,IAAI,mBAAA,EAAqB;AAEvB,YAAA,cAAA,CAAe,SAAS,CAAA;AAAA,UAC1B,CAAA,MAAO;AACL,YAAA,cAAA,EAAe;AACf,YAAA,YAAA,CAAa,SAAA,EAAW,QAAQ,OAAiB,CAAA;AAAA,UACnD;AAAA,QACF;AAAA,OACF;AAEA,MAAA,OAAO;AAAA,QACL,GAAG,OAAA;AAAA,QACH,gBAAA;AAAA,QACA,oBAAA;AAAA,QACA,OAAA,EAAS;AAAA,UACP,QAAA,EAAU,sBAAsB,UAAU,CAAA;AAAA,UAC1C,QAAA,EAAU,sBAAsB,UAAU,CAAA;AAAA,UAC1C,IAAA,EAAM,UAAA;AAAA,UACN,MAAA,EAAQ;AAAA;AACV,OACF;AAAA,IACF,CAAC,CAAA,GACD,QAAA;AAAA,EACN,CAAA,EAAG;AAAA,IACD,CAAA;AAAA,IACA,cAAA;AAAA,IACA,QAAA;AAAA,IACA,KAAA;AAAA,IACA,QAAA;AAAA,IACA,WAAA;AAAA,IACA,YAAA;AAAA,IACA,aAAA;AAAA,IACA,cAAA;AAAA,IACA,eAAA;AAAA,IACA,uBAAA;AAAA,IACA;AAAA,GACD,CAAA;AACH;;;;"}
@@ -1,8 +1,8 @@
1
- import React from 'react';
1
+ import { useState, useEffect } from 'react';
2
2
 
3
3
  const useIsMobile = () => {
4
- const [isMobile, setIsMobile] = React.useState(window.innerWidth <= 768);
5
- React.useEffect(() => {
4
+ const [isMobile, setIsMobile] = useState(window.innerWidth <= 768);
5
+ useEffect(() => {
6
6
  const handleResize = () => setIsMobile(window.innerWidth <= 768);
7
7
  window.addEventListener("resize", handleResize);
8
8
  return () => window.removeEventListener("resize", handleResize);
@@ -1 +1 @@
1
- {"version":3,"file":"useIsMobile.esm.js","sources":["../../src/hooks/useIsMobile.ts"],"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 */\nimport React from 'react';\n\nexport const useIsMobile = () => {\n const [isMobile, setIsMobile] = React.useState(window.innerWidth <= 768);\n\n React.useEffect(() => {\n const handleResize = () => setIsMobile(window.innerWidth <= 768);\n window.addEventListener('resize', handleResize);\n\n return () => window.removeEventListener('resize', handleResize);\n }, []);\n\n return isMobile;\n};\n"],"names":[],"mappings":";;AAiBO,MAAM,cAAc,MAAM;AAC/B,EAAA,MAAM,CAAC,UAAU,WAAW,CAAA,GAAI,MAAM,QAAA,CAAS,MAAA,CAAO,cAAc,GAAG,CAAA;AAEvE,EAAA,KAAA,CAAM,UAAU,MAAM;AACpB,IAAA,MAAM,YAAA,GAAe,MAAM,WAAA,CAAY,MAAA,CAAO,cAAc,GAAG,CAAA;AAC/D,IAAA,MAAA,CAAO,gBAAA,CAAiB,UAAU,YAAY,CAAA;AAE9C,IAAA,OAAO,MAAM,MAAA,CAAO,mBAAA,CAAoB,QAAA,EAAU,YAAY,CAAA;AAAA,EAChE,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,OAAO,QAAA;AACT;;;;"}
1
+ {"version":3,"file":"useIsMobile.esm.js","sources":["../../src/hooks/useIsMobile.ts"],"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 { useEffect, useState } from 'react';\n\nexport const useIsMobile = () => {\n const [isMobile, setIsMobile] = useState(window.innerWidth <= 768);\n\n useEffect(() => {\n const handleResize = () => setIsMobile(window.innerWidth <= 768);\n window.addEventListener('resize', handleResize);\n\n return () => window.removeEventListener('resize', handleResize);\n }, []);\n\n return isMobile;\n};\n"],"names":[],"mappings":";;AAkBO,MAAM,cAAc,MAAM;AAC/B,EAAA,MAAM,CAAC,QAAA,EAAU,WAAW,IAAI,QAAA,CAAS,MAAA,CAAO,cAAc,GAAG,CAAA;AAEjE,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,MAAM,YAAA,GAAe,MAAM,WAAA,CAAY,MAAA,CAAO,cAAc,GAAG,CAAA;AAC/D,IAAA,MAAA,CAAO,gBAAA,CAAiB,UAAU,YAAY,CAAA;AAE9C,IAAA,OAAO,MAAM,MAAA,CAAO,mBAAA,CAAoB,QAAA,EAAU,YAAY,CAAA;AAAA,EAChE,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,OAAO,QAAA;AACT;;;;"}
@@ -51,8 +51,7 @@ const intelligentAssistantTranslationDe = createTranslationMessages({
51
51
  "conversation.rename.confirm.action": "Umbenennen",
52
52
  "conversation.rename.confirm.title": "Chat umbenennen?",
53
53
  "conversation.rename.placeholder": "Chatname",
54
- "disclaimer.withValidation": "Diese Funktion nutzt KI-Technologie. Geben Sie bei Ihrer Eingabe keine pers\xF6nlichen oder sonstigen sensiblen Informationen an. Interaktionen k\xF6nnen dazu genutzt werden, die Produkte oder Dienstleistungen von Red Hat zu verbessern.",
55
- "disclaimer.withoutValidation": "Diese Funktion nutzt KI-Technologie. Geben Sie bei Ihrer Eingabe keine pers\xF6nlichen oder sonstigen sensiblen Informationen an. Interaktionen k\xF6nnen dazu genutzt werden, die Produkte oder Dienstleistungen von Red Hat zu verbessern.",
54
+ disclaimer: "Diese Funktion nutzt KI-Technologie. Geben Sie bei Ihrer Eingabe keine pers\xF6nlichen oder sonstigen sensiblen Informationen an. Interaktionen k\xF6nnen dazu genutzt werden, die Produkte oder Dienstleistungen von Red Hat zu verbessern.",
56
55
  "error.context.fileAttachment": "useFileAttachmentContext muss innerhalb eines FileAttachmentContextProvider liegen",
57
56
  "feedback.completion.body": "Wir haben Ihre Antwort erhalten. Vielen Dank f\xFCr Ihr Feedback!",
58
57
  "feedback.completion.title": "Feedback \xFCbermittelt",