@red-hat-developer-hub/backstage-plugin-intelligent-assistant 4.1.0 → 4.3.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 (57) hide show
  1. package/CHANGELOG.md +37 -0
  2. package/README.md +23 -0
  3. package/config.schema.json +117 -0
  4. package/dist/api/NotebooksApiClient.esm.js +3 -2
  5. package/dist/api/NotebooksApiClient.esm.js.map +1 -1
  6. package/dist/api/notebooksApi.esm.js.map +1 -1
  7. package/dist/components/LightSpeedChat.esm.js +280 -118
  8. package/dist/components/LightSpeedChat.esm.js.map +1 -1
  9. package/dist/components/LightspeedDrawerContext.esm.js.map +1 -1
  10. package/dist/components/LightspeedDrawerProvider.esm.js +5 -4
  11. package/dist/components/LightspeedDrawerProvider.esm.js.map +1 -1
  12. package/dist/components/ToastAlertGroup.esm.js +56 -0
  13. package/dist/components/ToastAlertGroup.esm.js.map +1 -0
  14. package/dist/components/notebooks/AddDocumentModal.esm.js +165 -144
  15. package/dist/components/notebooks/AddDocumentModal.esm.js.map +1 -1
  16. package/dist/components/notebooks/DeleteDocumentModal.esm.js +73 -38
  17. package/dist/components/notebooks/DeleteDocumentModal.esm.js.map +1 -1
  18. package/dist/components/notebooks/DeleteNotebookModal.esm.js +80 -40
  19. package/dist/components/notebooks/DeleteNotebookModal.esm.js.map +1 -1
  20. package/dist/components/notebooks/NotebookHeaderActions.esm.js +78 -0
  21. package/dist/components/notebooks/NotebookHeaderActions.esm.js.map +1 -0
  22. package/dist/components/notebooks/NotebookStreamProvider.esm.js +47 -0
  23. package/dist/components/notebooks/NotebookStreamProvider.esm.js.map +1 -0
  24. package/dist/components/notebooks/NotebookView.esm.js +284 -349
  25. package/dist/components/notebooks/NotebookView.esm.js.map +1 -1
  26. package/dist/components/notebooks/NotebooksTab.esm.js +2 -2
  27. package/dist/components/notebooks/NotebooksTab.esm.js.map +1 -1
  28. package/dist/components/notebooks/OverwriteConfirmModal.esm.js +126 -82
  29. package/dist/components/notebooks/OverwriteConfirmModal.esm.js.map +1 -1
  30. package/dist/components/notebooks/SidebarCollapseIcon.esm.js +8 -6
  31. package/dist/components/notebooks/SidebarCollapseIcon.esm.js.map +1 -1
  32. package/dist/components/notebooks/UploadResourceScreen.esm.js +1 -0
  33. package/dist/components/notebooks/UploadResourceScreen.esm.js.map +1 -1
  34. package/dist/components/notebooks/notebookDialogStyles.esm.js +40 -0
  35. package/dist/components/notebooks/notebookDialogStyles.esm.js.map +1 -0
  36. package/dist/components/notebooks/notebookStreamStore.esm.js +282 -0
  37. package/dist/components/notebooks/notebookStreamStore.esm.js.map +1 -0
  38. package/dist/hooks/notebooks/useCreateNotebookMessage.esm.js +3 -2
  39. package/dist/hooks/notebooks/useCreateNotebookMessage.esm.js.map +1 -1
  40. package/dist/hooks/useConversationMessages.esm.js +31 -108
  41. package/dist/hooks/useConversationMessages.esm.js.map +1 -1
  42. package/dist/hooks/useLightspeedProviderState.esm.js +14 -5
  43. package/dist/hooks/useLightspeedProviderState.esm.js.map +1 -1
  44. package/dist/index.esm.js +2 -2
  45. package/dist/index.esm.js.map +1 -1
  46. package/dist/utils/dom-extractor.esm.js +816 -0
  47. package/dist/utils/dom-extractor.esm.js.map +1 -0
  48. package/dist/utils/dom-selectors.esm.js +91 -0
  49. package/dist/utils/dom-selectors.esm.js.map +1 -0
  50. package/dist/utils/scoped-dialog-utils.esm.js +35 -0
  51. package/dist/utils/scoped-dialog-utils.esm.js.map +1 -0
  52. package/dist/utils/sensitive-data-redactor.esm.js +66 -0
  53. package/dist/utils/sensitive-data-redactor.esm.js.map +1 -0
  54. package/dist/utils/stream-event-helpers.esm.js +105 -0
  55. package/dist/utils/stream-event-helpers.esm.js.map +1 -0
  56. package/package.json +14 -14
  57. package/config.d.ts +0 -99
@@ -1 +1 @@
1
- {"version":3,"file":"LightspeedDrawerContext.esm.js","sources":["../../src/components/LightspeedDrawerContext.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 React, { createContext } from 'react';\n\nimport { ChatbotDisplayMode } from '@patternfly/chatbot';\n\nimport { FileContent } from '../types';\n\n/**\n * When switching to fullscreen (embedded), open the notebooks list or a specific session.\n *\n * @public\n */\nexport type LightspeedEmbeddedNotebooksTarget =\n 'notebooks' | { notebookSessionId: string };\n\n/**\n * Type for LightspeedDrawerContext\n *\n * @public\n */\nexport interface LightspeedDrawerContextType {\n /**\n * Whether the chatbot is active\n */\n isChatbotActive: boolean;\n /**\n * Toggle the chatbot open/closed\n */\n toggleChatbot: () => void;\n /**\n * The current display mode\n */\n displayMode: ChatbotDisplayMode;\n /**\n * Set the display mode (overlay, docked, or fullscreen/embedded).\n * When entering embedded mode, optional `embeddedNotebooks` navigates to\n * `/lightspeed/notebooks` (or a session URL) instead of the chat route.\n * Leaving embedded for overlay or docked resets the shell tab to Chat\n * (Notebooks is only available in fullscreen).\n */\n setDisplayMode: (\n mode: ChatbotDisplayMode,\n conversationIdParam?: string,\n embeddedNotebooks?: LightspeedEmbeddedNotebooksTarget,\n ) => void;\n /**\n * The drawer width (for docked mode)\n */\n drawerWidth: number;\n /**\n * The function for setting the drawer width\n */\n setDrawerWidth: React.Dispatch<React.SetStateAction<number>>;\n /**\n * The current conversation ID\n */\n currentConversationId?: string;\n /**\n * Set the current conversation ID and update the route if in embedded mode\n * Pass undefined to clear the conversation (example: for new chat)\n */\n setCurrentConversationId: (id: string | undefined) => void;\n /**\n * The message in the chat input box\n * Used to preserve input content when switching between display modes\n */\n draftMessage: string;\n /**\n * To save the input message as a draft when switching modes\n */\n setDraftMessage: (message: string) => void;\n /**\n * The file attachments in the chat input\n * Used to preserve file attachments when switching between display modes\n */\n draftFileContents: FileContent[];\n /**\n * To save file attachments as a draft when switching modes\n */\n setDraftFileContents: (files: FileContent[]) => void;\n /**\n * @internal After leaving fullscreen for overlay/docked, the next overlay/docked chat\n * mount should seed the thread from currentConversationId (or TEMP) instead of storage\n * lastOpened. Returns true at most once per handoff.\n */\n consumePendingOverlayThreadHandoff?: () => boolean;\n /**\n * Chat tab is 0, Notebooks tab is 1. Persisted across overlay/docked/fullscreen remounts\n * (each display mode mounts its own `LightspeedChat` tree).\n */\n shellViewTab: number;\n setShellViewTab: (tab: number) => void;\n}\n\nconst CONTEXT_KEY = '__lightspeed_drawer_context__' as keyof typeof globalThis;\n\nfunction getOrCreateContext() {\n const existing = (globalThis as any)[CONTEXT_KEY];\n if (existing)\n return existing as React.Context<LightspeedDrawerContextType | undefined>;\n const ctx = createContext<LightspeedDrawerContextType | undefined>(undefined);\n (globalThis as any)[CONTEXT_KEY] = ctx;\n return ctx;\n}\n\n/**\n * @public\n */\nexport const LightspeedDrawerContext = getOrCreateContext();\n"],"names":[],"mappings":";;AA6GA,MAAM,WAAA,GAAc,+BAAA;AAEpB,SAAS,kBAAA,GAAqB;AAC5B,EAAA,MAAM,QAAA,GAAY,WAAmB,WAAW,CAAA;AAChD,EAAA,IAAI,QAAA;AACF,IAAA,OAAO,QAAA;AACT,EAAA,MAAM,GAAA,GAAM,cAAuD,MAAS,CAAA;AAC5E,EAAC,UAAA,CAAmB,WAAW,CAAA,GAAI,GAAA;AACnC,EAAA,OAAO,GAAA;AACT;AAKO,MAAM,0BAA0B,kBAAA;;;;"}
1
+ {"version":3,"file":"LightspeedDrawerContext.esm.js","sources":["../../src/components/LightspeedDrawerContext.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 React, { createContext } from 'react';\n\nimport { ChatbotDisplayMode } from '@patternfly/chatbot';\n\nimport { FileContent } from '../types';\n\n/**\n * When switching to fullscreen (embedded), open the notebooks list or a specific session.\n *\n * @public\n */\nexport type LightspeedEmbeddedNotebooksTarget =\n 'notebooks' | { notebookSessionId: string };\n\n/**\n * Type for LightspeedDrawerContext\n *\n * @public\n */\nexport interface LightspeedDrawerContextType {\n /**\n * Whether the chatbot is active\n */\n isChatbotActive: boolean;\n /**\n * Toggle the chatbot open/closed\n */\n toggleChatbot: () => void;\n /**\n * The current display mode\n */\n displayMode: ChatbotDisplayMode;\n /**\n * Set the display mode (overlay, docked, or fullscreen/embedded).\n * When entering embedded mode, optional `embeddedNotebooks` navigates to\n * `/lightspeed/notebooks` (or a session URL) instead of the chat route.\n * Notebooks are available in all display modes; the shell tab and active\n * notebook are preserved across mode switches.\n */\n setDisplayMode: (\n mode: ChatbotDisplayMode,\n conversationIdParam?: string,\n embeddedNotebooks?: LightspeedEmbeddedNotebooksTarget,\n ) => void;\n /**\n * The drawer width (for docked mode)\n */\n drawerWidth: number;\n /**\n * The function for setting the drawer width\n */\n setDrawerWidth: React.Dispatch<React.SetStateAction<number>>;\n /**\n * The current conversation ID\n */\n currentConversationId?: string;\n /**\n * Set the current conversation ID and update the route if in embedded mode\n * Pass undefined to clear the conversation (example: for new chat)\n */\n setCurrentConversationId: (id: string | undefined) => void;\n /**\n * The message in the chat input box\n * Used to preserve input content when switching between display modes\n */\n draftMessage: string;\n /**\n * To save the input message as a draft when switching modes\n */\n setDraftMessage: (message: string) => void;\n /**\n * The file attachments in the chat input\n * Used to preserve file attachments when switching between display modes\n */\n draftFileContents: FileContent[];\n /**\n * To save file attachments as a draft when switching modes\n */\n setDraftFileContents: (files: FileContent[]) => void;\n /**\n * @internal After leaving fullscreen for overlay/docked, the next overlay/docked chat\n * mount should seed the thread from currentConversationId (or TEMP) instead of storage\n * lastOpened. Returns true at most once per handoff.\n */\n consumePendingOverlayThreadHandoff?: () => boolean;\n /**\n * Chat tab is 0, Notebooks tab is 1. Persisted across overlay/docked/fullscreen remounts\n * (each display mode mounts its own `LightspeedChat` tree).\n */\n shellViewTab: number;\n setShellViewTab: (tab: number) => void;\n /**\n * ID of the currently active notebook session, persisted across\n * overlay/docked/fullscreen remounts so display-mode switches preserve\n * the open notebook.\n */\n activeNotebookId: string | undefined;\n setActiveNotebookId: (id: string | undefined) => void;\n}\n\nconst CONTEXT_KEY = '__lightspeed_drawer_context__' as keyof typeof globalThis;\n\nfunction getOrCreateContext() {\n const existing = (globalThis as any)[CONTEXT_KEY];\n if (existing)\n return existing as React.Context<LightspeedDrawerContextType | undefined>;\n const ctx = createContext<LightspeedDrawerContextType | undefined>(undefined);\n (globalThis as any)[CONTEXT_KEY] = ctx;\n return ctx;\n}\n\n/**\n * @public\n */\nexport const LightspeedDrawerContext = getOrCreateContext();\n"],"names":[],"mappings":";;AAoHA,MAAM,WAAA,GAAc,+BAAA;AAEpB,SAAS,kBAAA,GAAqB;AAC5B,EAAA,MAAM,QAAA,GAAY,WAAmB,WAAW,CAAA;AAChD,EAAA,IAAI,QAAA;AACF,IAAA,OAAO,QAAA;AACT,EAAA,MAAM,GAAA,GAAM,cAAuD,MAAS,CAAA;AAC5E,EAAC,UAAA,CAAmB,WAAW,CAAA,GAAI,GAAA;AACnC,EAAA,OAAO,GAAA;AACT;AAKO,MAAM,0BAA0B,kBAAA;;;;"}
@@ -1,10 +1,11 @@
1
- import { jsxs, jsx } from 'react/jsx-runtime';
1
+ import { jsx, jsxs } from 'react/jsx-runtime';
2
2
  import { makeStyles } from '@mui/styles';
3
3
  import { ChatbotModal } from '@patternfly/chatbot';
4
4
  import { DOCKED_CONTENT_OFFSET } from '../const.esm.js';
5
5
  import { useLightspeedProviderState } from '../hooks/useLightspeedProviderState.esm.js';
6
6
  import { LightspeedChatContainer } from './LightspeedChatContainer.esm.js';
7
7
  import { LightspeedDrawerContext } from './LightspeedDrawerContext.esm.js';
8
+ import { NotebookStreamProvider } from './notebooks/NotebookStreamProvider.esm.js';
8
9
 
9
10
  const useStyles = makeStyles((theme) => ({
10
11
  chatbotModal: {
@@ -12,7 +13,7 @@ const useStyles = makeStyles((theme) => ({
12
13
  bottom: `calc(${theme?.spacing?.(2) ?? "16px"} + 5em)`,
13
14
  right: `calc(${theme?.spacing?.(2) ?? "16px"} + 1.5em)`,
14
15
  maxWidth: "min(30rem, calc(100vw - 32px)) !important",
15
- overflowX: "hidden",
16
+ overflow: "hidden",
16
17
  transition: "margin-right 0.3s ease",
17
18
  "body.docked-drawer-open &": {
18
19
  marginRight: DOCKED_CONTENT_OFFSET
@@ -22,7 +23,7 @@ const useStyles = makeStyles((theme) => ({
22
23
  const LightspeedDrawerProvider = ({ children }) => {
23
24
  const classes = useStyles();
24
25
  const { contextValue, shouldRenderOverlayModal, closeChatbot } = useLightspeedProviderState();
25
- return /* @__PURE__ */ jsxs(LightspeedDrawerContext.Provider, { value: contextValue, children: [
26
+ return /* @__PURE__ */ jsx(LightspeedDrawerContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsxs(NotebookStreamProvider, { children: [
26
27
  children,
27
28
  shouldRenderOverlayModal && /* @__PURE__ */ jsx(
28
29
  ChatbotModal,
@@ -37,7 +38,7 @@ const LightspeedDrawerProvider = ({ children }) => {
37
38
  children: /* @__PURE__ */ jsx(LightspeedChatContainer, {})
38
39
  }
39
40
  )
40
- ] });
41
+ ] }) });
41
42
  };
42
43
 
43
44
  export { LightspeedDrawerProvider };
@@ -1 +1 @@
1
- {"version":3,"file":"LightspeedDrawerProvider.esm.js","sources":["../../src/components/LightspeedDrawerProvider.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 { PropsWithChildren } from 'react';\n\nimport { makeStyles } from '@mui/styles';\nimport { ChatbotModal } from '@patternfly/chatbot';\n\nimport { DOCKED_CONTENT_OFFSET } from '../const';\nimport { useLightspeedProviderState } from '../hooks/useLightspeedProviderState';\nimport { LightspeedChatContainer } from './LightspeedChatContainer';\nimport { LightspeedDrawerContext } from './LightspeedDrawerContext';\n\nconst useStyles = makeStyles(theme => ({\n chatbotModal: {\n boxShadow:\n '0 14px 20px -7px rgba(0, 0, 0, 0.22), 0 32px 50px 6px rgba(0, 0, 0, 0.16), 0 12px 60px 12px rgba(0, 0, 0, 0.14) !important',\n bottom: `calc(${theme?.spacing?.(2) ?? '16px'} + 5em)`,\n right: `calc(${theme?.spacing?.(2) ?? '16px'} + 1.5em)`,\n maxWidth: 'min(30rem, calc(100vw - 32px)) !important',\n overflowX: 'hidden' as const,\n transition: 'margin-right 0.3s ease',\n 'body.docked-drawer-open &': {\n marginRight: DOCKED_CONTENT_OFFSET,\n },\n },\n}));\n\n/**\n * @public\n */\nexport const LightspeedDrawerProvider = ({ children }: PropsWithChildren) => {\n const classes = useStyles();\n const { contextValue, shouldRenderOverlayModal, closeChatbot } =\n useLightspeedProviderState();\n\n return (\n <LightspeedDrawerContext.Provider value={contextValue}>\n {children}\n {shouldRenderOverlayModal && (\n <ChatbotModal\n isOpen\n displayMode={contextValue.displayMode}\n disableFocusTrap\n onEscapePress={() => closeChatbot()}\n ouiaId=\"LightspeedChatbotModal\"\n aria-labelledby=\"lightspeed-chatpopup-modal\"\n className={classes.chatbotModal}\n >\n <LightspeedChatContainer />\n </ChatbotModal>\n )}\n </LightspeedDrawerContext.Provider>\n );\n};\n"],"names":[],"mappings":";;;;;;;;AA0BA,MAAM,SAAA,GAAY,WAAW,CAAA,KAAA,MAAU;AAAA,EACrC,YAAA,EAAc;AAAA,IACZ,SAAA,EACE,4HAAA;AAAA,IACF,QAAQ,CAAA,KAAA,EAAQ,KAAA,EAAO,OAAA,GAAU,CAAC,KAAK,MAAM,CAAA,OAAA,CAAA;AAAA,IAC7C,OAAO,CAAA,KAAA,EAAQ,KAAA,EAAO,OAAA,GAAU,CAAC,KAAK,MAAM,CAAA,SAAA,CAAA;AAAA,IAC5C,QAAA,EAAU,2CAAA;AAAA,IACV,SAAA,EAAW,QAAA;AAAA,IACX,UAAA,EAAY,wBAAA;AAAA,IACZ,2BAAA,EAA6B;AAAA,MAC3B,WAAA,EAAa;AAAA;AACf;AAEJ,CAAA,CAAE,CAAA;AAKK,MAAM,wBAAA,GAA2B,CAAC,EAAE,QAAA,EAAS,KAAyB;AAC3E,EAAA,MAAM,UAAU,SAAA,EAAU;AAC1B,EAAA,MAAM,EAAE,YAAA,EAAc,wBAAA,EAA0B,YAAA,KAC9C,0BAAA,EAA2B;AAE7B,EAAA,uBACE,IAAA,CAAC,uBAAA,CAAwB,QAAA,EAAxB,EAAiC,OAAO,YAAA,EACtC,QAAA,EAAA;AAAA,IAAA,QAAA;AAAA,IACA,wBAAA,oBACC,GAAA;AAAA,MAAC,YAAA;AAAA,MAAA;AAAA,QACC,MAAA,EAAM,IAAA;AAAA,QACN,aAAa,YAAA,CAAa,WAAA;AAAA,QAC1B,gBAAA,EAAgB,IAAA;AAAA,QAChB,aAAA,EAAe,MAAM,YAAA,EAAa;AAAA,QAClC,MAAA,EAAO,wBAAA;AAAA,QACP,iBAAA,EAAgB,4BAAA;AAAA,QAChB,WAAW,OAAA,CAAQ,YAAA;AAAA,QAEnB,8BAAC,uBAAA,EAAA,EAAwB;AAAA;AAAA;AAC3B,GAAA,EAEJ,CAAA;AAEJ;;;;"}
1
+ {"version":3,"file":"LightspeedDrawerProvider.esm.js","sources":["../../src/components/LightspeedDrawerProvider.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 { PropsWithChildren } from 'react';\n\nimport { makeStyles } from '@mui/styles';\nimport { ChatbotModal } from '@patternfly/chatbot';\n\nimport { DOCKED_CONTENT_OFFSET } from '../const';\nimport { useLightspeedProviderState } from '../hooks/useLightspeedProviderState';\nimport { LightspeedChatContainer } from './LightspeedChatContainer';\nimport { LightspeedDrawerContext } from './LightspeedDrawerContext';\nimport { NotebookStreamProvider } from './notebooks/NotebookStreamProvider';\n\nconst useStyles = makeStyles(theme => ({\n chatbotModal: {\n boxShadow:\n '0 14px 20px -7px rgba(0, 0, 0, 0.22), 0 32px 50px 6px rgba(0, 0, 0, 0.16), 0 12px 60px 12px rgba(0, 0, 0, 0.14) !important',\n bottom: `calc(${theme?.spacing?.(2) ?? '16px'} + 5em)`,\n right: `calc(${theme?.spacing?.(2) ?? '16px'} + 1.5em)`,\n maxWidth: 'min(30rem, calc(100vw - 32px)) !important',\n overflow: 'hidden' as const,\n transition: 'margin-right 0.3s ease',\n 'body.docked-drawer-open &': {\n marginRight: DOCKED_CONTENT_OFFSET,\n },\n },\n}));\n\n/**\n * @public\n */\nexport const LightspeedDrawerProvider = ({ children }: PropsWithChildren) => {\n const classes = useStyles();\n const { contextValue, shouldRenderOverlayModal, closeChatbot } =\n useLightspeedProviderState();\n\n return (\n <LightspeedDrawerContext.Provider value={contextValue}>\n <NotebookStreamProvider>\n {children}\n {shouldRenderOverlayModal && (\n <ChatbotModal\n isOpen\n displayMode={contextValue.displayMode}\n disableFocusTrap\n onEscapePress={() => closeChatbot()}\n ouiaId=\"LightspeedChatbotModal\"\n aria-labelledby=\"lightspeed-chatpopup-modal\"\n className={classes.chatbotModal}\n >\n <LightspeedChatContainer />\n </ChatbotModal>\n )}\n </NotebookStreamProvider>\n </LightspeedDrawerContext.Provider>\n );\n};\n"],"names":[],"mappings":";;;;;;;;;AA2BA,MAAM,SAAA,GAAY,WAAW,CAAA,KAAA,MAAU;AAAA,EACrC,YAAA,EAAc;AAAA,IACZ,SAAA,EACE,4HAAA;AAAA,IACF,QAAQ,CAAA,KAAA,EAAQ,KAAA,EAAO,OAAA,GAAU,CAAC,KAAK,MAAM,CAAA,OAAA,CAAA;AAAA,IAC7C,OAAO,CAAA,KAAA,EAAQ,KAAA,EAAO,OAAA,GAAU,CAAC,KAAK,MAAM,CAAA,SAAA,CAAA;AAAA,IAC5C,QAAA,EAAU,2CAAA;AAAA,IACV,QAAA,EAAU,QAAA;AAAA,IACV,UAAA,EAAY,wBAAA;AAAA,IACZ,2BAAA,EAA6B;AAAA,MAC3B,WAAA,EAAa;AAAA;AACf;AAEJ,CAAA,CAAE,CAAA;AAKK,MAAM,wBAAA,GAA2B,CAAC,EAAE,QAAA,EAAS,KAAyB;AAC3E,EAAA,MAAM,UAAU,SAAA,EAAU;AAC1B,EAAA,MAAM,EAAE,YAAA,EAAc,wBAAA,EAA0B,YAAA,KAC9C,0BAAA,EAA2B;AAE7B,EAAA,2BACG,uBAAA,CAAwB,QAAA,EAAxB,EAAiC,KAAA,EAAO,YAAA,EACvC,+BAAC,sBAAA,EAAA,EACE,QAAA,EAAA;AAAA,IAAA,QAAA;AAAA,IACA,wBAAA,oBACC,GAAA;AAAA,MAAC,YAAA;AAAA,MAAA;AAAA,QACC,MAAA,EAAM,IAAA;AAAA,QACN,aAAa,YAAA,CAAa,WAAA;AAAA,QAC1B,gBAAA,EAAgB,IAAA;AAAA,QAChB,aAAA,EAAe,MAAM,YAAA,EAAa;AAAA,QAClC,MAAA,EAAO,wBAAA;AAAA,QACP,iBAAA,EAAgB,4BAAA;AAAA,QAChB,WAAW,OAAA,CAAQ,YAAA;AAAA,QAEnB,8BAAC,uBAAA,EAAA,EAAwB;AAAA;AAAA;AAC3B,GAAA,EAEJ,CAAA,EACF,CAAA;AAEJ;;;;"}
@@ -0,0 +1,56 @@
1
+ import { jsx } from 'react/jsx-runtime';
2
+ import { makeStyles } from '@material-ui/core';
3
+ import { AlertGroup, Alert, AlertVariant, AlertActionCloseButton } from '@patternfly/react-core';
4
+
5
+ const useStyles = makeStyles((theme) => ({
6
+ toastAlertGroup: {
7
+ "--pf-v6-c-alert-group--m-toast--InsetInlineEnd": `${theme.spacing(2.5)}px`,
8
+ "--pf-v6-c-alert-group--m-toast--InsetBlockStart": `${theme.spacing(2.5)}px`,
9
+ "--pf-v6-c-alert-group--m-toast--MaxWidth": "350px",
10
+ "--pf-v6-c-alert-group--m-toast--ZIndex": "9999"
11
+ },
12
+ toastAlert: {
13
+ maxWidth: "350px",
14
+ "& .pf-v6-c-alert__title": {
15
+ margin: 0
16
+ }
17
+ }
18
+ }));
19
+ const ToastAlertGroup = ({
20
+ alerts,
21
+ onRemoveAlert
22
+ }) => {
23
+ const classes = useStyles();
24
+ if (alerts.length === 0) return null;
25
+ return /* @__PURE__ */ jsx(
26
+ AlertGroup,
27
+ {
28
+ hasAnimations: true,
29
+ isToast: true,
30
+ isLiveRegion: true,
31
+ className: classes.toastAlertGroup,
32
+ children: alerts.map(({ key, title, variant }) => /* @__PURE__ */ jsx(
33
+ Alert,
34
+ {
35
+ variant: AlertVariant[variant ?? "success"],
36
+ title,
37
+ className: classes.toastAlert,
38
+ timeout: 2e3,
39
+ onTimeout: () => onRemoveAlert(key),
40
+ actionClose: /* @__PURE__ */ jsx(
41
+ AlertActionCloseButton,
42
+ {
43
+ title,
44
+ variantLabel: `${variant ?? "success"} alert`,
45
+ onClose: () => onRemoveAlert(key)
46
+ }
47
+ )
48
+ },
49
+ key
50
+ ))
51
+ }
52
+ );
53
+ };
54
+
55
+ export { ToastAlertGroup };
56
+ //# sourceMappingURL=ToastAlertGroup.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ToastAlertGroup.esm.js","sources":["../../src/components/ToastAlertGroup.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 React from 'react';\n\nimport { makeStyles } from '@material-ui/core';\nimport {\n Alert,\n AlertActionCloseButton,\n AlertGroup,\n AlertVariant,\n type AlertProps,\n} from '@patternfly/react-core';\n\nconst useStyles = makeStyles(theme => ({\n toastAlertGroup: {\n '--pf-v6-c-alert-group--m-toast--InsetInlineEnd': `${theme.spacing(2.5)}px`,\n '--pf-v6-c-alert-group--m-toast--InsetBlockStart': `${theme.spacing(2.5)}px`,\n '--pf-v6-c-alert-group--m-toast--MaxWidth': '350px',\n '--pf-v6-c-alert-group--m-toast--ZIndex': '9999',\n },\n toastAlert: {\n maxWidth: '350px',\n '& .pf-v6-c-alert__title': {\n margin: 0,\n },\n },\n}));\n\ntype ToastAlertGroupProps = {\n alerts: Partial<AlertProps>[];\n onRemoveAlert: (key: React.Key) => void;\n};\n\nexport const ToastAlertGroup = ({\n alerts,\n onRemoveAlert,\n}: ToastAlertGroupProps) => {\n const classes = useStyles();\n\n if (alerts.length === 0) return null;\n\n return (\n <AlertGroup\n hasAnimations\n isToast\n isLiveRegion\n className={classes.toastAlertGroup}\n >\n {alerts.map(({ key, title, variant }) => (\n <Alert\n key={key}\n variant={AlertVariant[variant ?? 'success']}\n title={title}\n className={classes.toastAlert}\n timeout={2000}\n onTimeout={() => onRemoveAlert(key as React.Key)}\n actionClose={\n <AlertActionCloseButton\n title={title as string}\n variantLabel={`${variant ?? 'success'} alert`}\n onClose={() => onRemoveAlert(key as React.Key)}\n />\n }\n />\n ))}\n </AlertGroup>\n );\n};\n"],"names":[],"mappings":";;;;AA2BA,MAAM,SAAA,GAAY,WAAW,CAAA,KAAA,MAAU;AAAA,EACrC,eAAA,EAAiB;AAAA,IACf,gDAAA,EAAkD,CAAA,EAAG,KAAA,CAAM,OAAA,CAAQ,GAAG,CAAC,CAAA,EAAA,CAAA;AAAA,IACvE,iDAAA,EAAmD,CAAA,EAAG,KAAA,CAAM,OAAA,CAAQ,GAAG,CAAC,CAAA,EAAA,CAAA;AAAA,IACxE,0CAAA,EAA4C,OAAA;AAAA,IAC5C,wCAAA,EAA0C;AAAA,GAC5C;AAAA,EACA,UAAA,EAAY;AAAA,IACV,QAAA,EAAU,OAAA;AAAA,IACV,yBAAA,EAA2B;AAAA,MACzB,MAAA,EAAQ;AAAA;AACV;AAEJ,CAAA,CAAE,CAAA;AAOK,MAAM,kBAAkB,CAAC;AAAA,EAC9B,MAAA;AAAA,EACA;AACF,CAAA,KAA4B;AAC1B,EAAA,MAAM,UAAU,SAAA,EAAU;AAE1B,EAAA,IAAI,MAAA,CAAO,MAAA,KAAW,CAAA,EAAG,OAAO,IAAA;AAEhC,EAAA,uBACE,GAAA;AAAA,IAAC,UAAA;AAAA,IAAA;AAAA,MACC,aAAA,EAAa,IAAA;AAAA,MACb,OAAA,EAAO,IAAA;AAAA,MACP,YAAA,EAAY,IAAA;AAAA,MACZ,WAAW,OAAA,CAAQ,eAAA;AAAA,MAElB,iBAAO,GAAA,CAAI,CAAC,EAAE,GAAA,EAAK,KAAA,EAAO,SAAQ,qBACjC,GAAA;AAAA,QAAC,KAAA;AAAA,QAAA;AAAA,UAEC,OAAA,EAAS,YAAA,CAAa,OAAA,IAAW,SAAS,CAAA;AAAA,UAC1C,KAAA;AAAA,UACA,WAAW,OAAA,CAAQ,UAAA;AAAA,UACnB,OAAA,EAAS,GAAA;AAAA,UACT,SAAA,EAAW,MAAM,aAAA,CAAc,GAAgB,CAAA;AAAA,UAC/C,WAAA,kBACE,GAAA;AAAA,YAAC,sBAAA;AAAA,YAAA;AAAA,cACC,KAAA;AAAA,cACA,YAAA,EAAc,CAAA,EAAG,OAAA,IAAW,SAAS,CAAA,MAAA,CAAA;AAAA,cACrC,OAAA,EAAS,MAAM,aAAA,CAAc,GAAgB;AAAA;AAAA;AAC/C,SAAA;AAAA,QAXG;AAAA,OAcR;AAAA;AAAA,GACH;AAEJ;;;;"}
@@ -17,34 +17,21 @@ import { useUploadDocument } from '../../hooks/notebooks/useUploadDocument.esm.j
17
17
  import { useTranslation } from '../../hooks/useTranslation.esm.js';
18
18
  import { runFileUploads } from '../../utils/notebook-upload-runner.esm.js';
19
19
  import { getNotebookAcceptedFileTypes, validateFiles } from '../../utils/notebook-upload-utils.esm.js';
20
+ import { getScopedDialogProps } from '../../utils/scoped-dialog-utils.esm.js';
20
21
  import { FileListItem } from './FileListItem.esm.js';
22
+ import { notebookDialogStyles } from './notebookDialogStyles.esm.js';
21
23
 
22
24
  const UNIQUE_FILE_TYPE_LABELS = [
23
25
  ...new Set(Object.values(NOTEBOOK_EXTENSION_TO_FILE_TYPE))
24
26
  ].map((t) => t.toUpperCase());
25
27
  const useStyles = makeStyles((theme) => ({
26
- dialogPaper: {
27
- borderRadius: 24,
28
- maxWidth: 578
29
- },
30
- dialogTitle: {
31
- display: "flex",
32
- alignItems: "center",
33
- justifyContent: "space-between",
34
- padding: "24px 24px 16px"
35
- },
36
- titleText: {
37
- fontWeight: 500,
38
- fontSize: "1.25rem",
39
- lineHeight: "1.625rem",
28
+ ...notebookDialogStyles(theme),
29
+ titleTextCompact: {
30
+ fontWeight: 600,
31
+ fontSize: "1.125rem",
32
+ lineHeight: "1.5rem",
40
33
  letterSpacing: "-0.25px"
41
34
  },
42
- closeButton: {
43
- color: theme.palette.text.primary
44
- },
45
- dialogContent: {
46
- padding: "0 24px 24px"
47
- },
48
35
  errorAlert: {
49
36
  marginBottom: theme.spacing(2),
50
37
  "--pf-v6-c-alert--PaddingBlockEnd": "0",
@@ -91,6 +78,11 @@ const useStyles = makeStyles((theme) => ({
91
78
  justifyContent: "flex-start",
92
79
  gap: theme.spacing(1)
93
80
  },
81
+ dialogActionsCompact: {
82
+ padding: "12px 16px !important",
83
+ justifyContent: "flex-start",
84
+ gap: theme.spacing(1)
85
+ },
94
86
  addButton: {
95
87
  textTransform: "none"
96
88
  },
@@ -172,7 +164,8 @@ const AddDocumentModal = ({
172
164
  onUploadFailed,
173
165
  onDuplicatesFound,
174
166
  filesToAdd,
175
- onFilesAdded
167
+ onFilesAdded,
168
+ isCompact = false
176
169
  }) => {
177
170
  const classes = useStyles();
178
171
  const { t } = useTranslation();
@@ -241,142 +234,170 @@ const AddDocumentModal = ({
241
234
  setValidationErrors([]);
242
235
  onClose();
243
236
  };
237
+ const scopedProps = getScopedDialogProps(isCompact);
244
238
  return /* @__PURE__ */ jsxs(
245
239
  Dialog,
246
240
  {
247
241
  open: isOpen,
248
242
  onClose: handleClose,
249
243
  "aria-labelledby": "add-document-modal-title",
244
+ ...scopedProps,
250
245
  PaperProps: {
251
- className: classes.dialogPaper
246
+ className: isCompact ? classes.dialogPaperCompact : classes.dialogPaper,
247
+ ...scopedProps.PaperProps
252
248
  },
253
249
  children: [
254
- /* @__PURE__ */ jsxs(DialogTitle, { className: classes.dialogTitle, children: [
255
- /* @__PURE__ */ jsxs(Typography, { component: "h2", className: classes.titleText, children: [
256
- t("notebook.upload.modal.title"),
257
- selectedFiles.length > 0 && ` (${selectedFiles.length}/${NOTEBOOK_MAX_FILES - existingDocumentNames.length})`
258
- ] }),
259
- /* @__PURE__ */ jsx(
260
- IconButton,
261
- {
262
- "aria-label": t("common.close"),
263
- onClick: handleClose,
264
- className: classes.closeButton,
265
- size: "small",
266
- children: /* @__PURE__ */ jsx(CloseIcon, {})
267
- }
268
- )
269
- ] }),
270
- /* @__PURE__ */ jsxs(DialogContent, { className: classes.dialogContent, children: [
271
- validationErrors.length > 0 && /* @__PURE__ */ jsx(
272
- Alert,
273
- {
274
- variant: "danger",
275
- isInline: true,
276
- className: classes.errorAlert,
277
- title: validationErrors.map((errorKey) => {
278
- const message = t(errorKey);
279
- return errorKey === "notebook.upload.error.tooManyFiles" ? message.replace("{{max}}", String(NOTEBOOK_MAX_FILES)) : message;
280
- }).join("\n")
281
- }
282
- ),
283
- hasUploadsInProgress && /* @__PURE__ */ jsx(
284
- Alert,
285
- {
286
- variant: "info",
287
- isInline: true,
288
- className: classes.errorAlert,
289
- title: t("notebook.view.documents.uploadsInProgress")
290
- }
291
- ),
292
- (() => {
293
- const isDropzoneDisabled = remainingSlots <= 0;
294
- const dropzoneContent = /* @__PURE__ */ jsx(
295
- MultipleFileUpload,
296
- {
297
- className: `${classes.dropzone} ${isDropzoneDisabled ? classes.dropzoneDisabled : ""}`,
298
- dropzoneProps: {
299
- accept: getNotebookAcceptedFileTypes(),
300
- onDropRejected: handleDropRejected,
301
- disabled: isDropzoneDisabled
302
- },
303
- onFileDrop: handleFileDrop,
304
- children: /* @__PURE__ */ jsxs(
305
- DropzoneClickArea,
250
+ /* @__PURE__ */ jsxs(
251
+ DialogTitle,
252
+ {
253
+ className: isCompact ? classes.dialogTitleCompact : classes.dialogTitle,
254
+ children: [
255
+ /* @__PURE__ */ jsxs(
256
+ Typography,
257
+ {
258
+ component: "h2",
259
+ className: isCompact ? classes.titleTextCompact : classes.titleText,
260
+ children: [
261
+ t("notebook.upload.modal.title"),
262
+ selectedFiles.length > 0 && ` (${selectedFiles.length}/${NOTEBOOK_MAX_FILES - existingDocumentNames.length})`
263
+ ]
264
+ }
265
+ ),
266
+ /* @__PURE__ */ jsx(
267
+ IconButton,
268
+ {
269
+ "aria-label": t("common.close"),
270
+ onClick: handleClose,
271
+ className: classes.closeButton,
272
+ size: "small",
273
+ children: /* @__PURE__ */ jsx(CloseIcon, {})
274
+ }
275
+ )
276
+ ]
277
+ }
278
+ ),
279
+ /* @__PURE__ */ jsxs(
280
+ DialogContent,
281
+ {
282
+ className: isCompact ? classes.dialogContentCompact : classes.dialogContent,
283
+ children: [
284
+ validationErrors.length > 0 && /* @__PURE__ */ jsx(
285
+ Alert,
286
+ {
287
+ variant: "danger",
288
+ isInline: true,
289
+ className: classes.errorAlert,
290
+ title: validationErrors.map((errorKey) => {
291
+ const message = t(errorKey);
292
+ return errorKey === "notebook.upload.error.tooManyFiles" ? message.replace("{{max}}", String(NOTEBOOK_MAX_FILES)) : message;
293
+ }).join("\n")
294
+ }
295
+ ),
296
+ hasUploadsInProgress && /* @__PURE__ */ jsx(
297
+ Alert,
298
+ {
299
+ variant: "info",
300
+ isInline: true,
301
+ className: classes.errorAlert,
302
+ title: t("notebook.view.documents.uploadsInProgress")
303
+ }
304
+ ),
305
+ (() => {
306
+ const isDropzoneDisabled = remainingSlots <= 0;
307
+ const dropzoneContent = /* @__PURE__ */ jsx(
308
+ MultipleFileUpload,
306
309
  {
307
- isDisabled: isDropzoneDisabled,
308
- ariaLabel: t("notebook.upload.modal.dragDropTitle"),
309
- children: [
310
- /* @__PURE__ */ jsx(
311
- MultipleFileUploadMain,
312
- {
313
- titleIcon: /* @__PURE__ */ jsx(UploadIcon, { className: classes.uploadIcon }),
314
- titleText: t("notebook.upload.modal.dragDropTitle"),
315
- isUploadButtonHidden: true
316
- }
317
- ),
318
- /* @__PURE__ */ jsx(Typography, { className: classes.supportedFormatsLabel, children: t("notebook.upload.modal.supportedFormats") }),
319
- /* @__PURE__ */ jsx("div", { className: classes.chipContainer, children: UNIQUE_FILE_TYPE_LABELS.map((label) => /* @__PURE__ */ jsx("span", { className: classes.fileTypeChip, children: label }, label)) }),
320
- /* @__PURE__ */ jsx(Typography, { className: classes.maxFileSizeText, children: t("notebook.upload.modal.maxFileSize") })
321
- ]
310
+ className: `${classes.dropzone} ${isDropzoneDisabled ? classes.dropzoneDisabled : ""}`,
311
+ dropzoneProps: {
312
+ accept: getNotebookAcceptedFileTypes(),
313
+ onDropRejected: handleDropRejected,
314
+ disabled: isDropzoneDisabled
315
+ },
316
+ onFileDrop: handleFileDrop,
317
+ children: /* @__PURE__ */ jsxs(
318
+ DropzoneClickArea,
319
+ {
320
+ isDisabled: isDropzoneDisabled,
321
+ ariaLabel: t("notebook.upload.modal.dragDropTitle"),
322
+ children: [
323
+ /* @__PURE__ */ jsx(
324
+ MultipleFileUploadMain,
325
+ {
326
+ titleIcon: /* @__PURE__ */ jsx(UploadIcon, { className: classes.uploadIcon }),
327
+ titleText: t("notebook.upload.modal.dragDropTitle"),
328
+ isUploadButtonHidden: true
329
+ }
330
+ ),
331
+ /* @__PURE__ */ jsx(Typography, { className: classes.supportedFormatsLabel, children: t("notebook.upload.modal.supportedFormats") }),
332
+ /* @__PURE__ */ jsx("div", { className: classes.chipContainer, children: UNIQUE_FILE_TYPE_LABELS.map((label) => /* @__PURE__ */ jsx("span", { className: classes.fileTypeChip, children: label }, label)) }),
333
+ /* @__PURE__ */ jsx(Typography, { className: classes.maxFileSizeText, children: t("notebook.upload.modal.maxFileSize") })
334
+ ]
335
+ }
336
+ )
322
337
  }
323
- )
324
- }
325
- );
326
- return isDropzoneDisabled ? /* @__PURE__ */ jsx(
327
- Tooltip,
328
- {
329
- content: t("notebook.view.documents.maxReached"),
330
- position: "top",
331
- children: /* @__PURE__ */ jsx("div", { children: dropzoneContent })
332
- }
333
- ) : dropzoneContent;
334
- })(),
335
- selectedFiles.length > 0 && /* @__PURE__ */ jsxs(Box, { className: classes.fileListContainer, children: [
336
- /* @__PURE__ */ jsx(Box, { className: classes.fileListHeader, children: /* @__PURE__ */ jsx(Typography, { className: classes.fileCount, children: t("notebook.upload.modal.selectedFiles", {
337
- count: selectedFiles.length,
338
- max: NOTEBOOK_MAX_FILES - existingDocumentNames.length
339
- }) }) }),
340
- selectedFiles.map((file, index) => /* @__PURE__ */ jsx(
341
- FileListItem,
342
- {
343
- file,
344
- onRemove: () => handleRemoveFile(index),
345
- removeAriaLabel: t(
346
- "notebook.upload.modal.removeFile",
338
+ );
339
+ return isDropzoneDisabled ? /* @__PURE__ */ jsx(
340
+ Tooltip,
347
341
  {
348
- fileName: file.name
342
+ content: t("notebook.view.documents.maxReached"),
343
+ position: "top",
344
+ children: /* @__PURE__ */ jsx("div", { children: dropzoneContent })
349
345
  }
350
- )
351
- },
352
- `${file.name}-${index}`
353
- ))
354
- ] })
355
- ] }),
356
- /* @__PURE__ */ jsxs(DialogActions, { className: classes.dialogActions, children: [
357
- /* @__PURE__ */ jsx(
358
- Button,
359
- {
360
- onClick: handleAddFiles,
361
- className: classes.addButton,
362
- variant: "contained",
363
- color: "primary",
364
- disabled: selectedFiles.length === 0 || hasUploadsInProgress,
365
- children: selectedFiles.length > 0 ? t("notebook.upload.modal.addButton", {
366
- count: selectedFiles.length
367
- }) : t("notebook.upload.modal.addButtonEmpty")
368
- }
369
- ),
370
- /* @__PURE__ */ jsx(
371
- Button,
372
- {
373
- onClick: handleClose,
374
- className: classes.cancelButton,
375
- color: "inherit",
376
- children: t("common.cancel")
377
- }
378
- )
379
- ] })
346
+ ) : dropzoneContent;
347
+ })(),
348
+ selectedFiles.length > 0 && /* @__PURE__ */ jsxs(Box, { className: classes.fileListContainer, children: [
349
+ /* @__PURE__ */ jsx(Box, { className: classes.fileListHeader, children: /* @__PURE__ */ jsx(Typography, { className: classes.fileCount, children: t("notebook.upload.modal.selectedFiles", {
350
+ count: selectedFiles.length,
351
+ max: NOTEBOOK_MAX_FILES - existingDocumentNames.length
352
+ }) }) }),
353
+ selectedFiles.map((file, index) => /* @__PURE__ */ jsx(
354
+ FileListItem,
355
+ {
356
+ file,
357
+ onRemove: () => handleRemoveFile(index),
358
+ removeAriaLabel: t(
359
+ "notebook.upload.modal.removeFile",
360
+ {
361
+ fileName: file.name
362
+ }
363
+ )
364
+ },
365
+ `${file.name}-${index}`
366
+ ))
367
+ ] })
368
+ ]
369
+ }
370
+ ),
371
+ /* @__PURE__ */ jsxs(
372
+ DialogActions,
373
+ {
374
+ className: isCompact ? classes.dialogActionsCompact : classes.dialogActions,
375
+ children: [
376
+ /* @__PURE__ */ jsx(
377
+ Button,
378
+ {
379
+ onClick: handleAddFiles,
380
+ className: classes.addButton,
381
+ variant: "contained",
382
+ color: "primary",
383
+ disabled: selectedFiles.length === 0 || hasUploadsInProgress,
384
+ children: selectedFiles.length > 0 ? t("notebook.upload.modal.addButton", {
385
+ count: selectedFiles.length
386
+ }) : t("notebook.upload.modal.addButtonEmpty")
387
+ }
388
+ ),
389
+ /* @__PURE__ */ jsx(
390
+ Button,
391
+ {
392
+ onClick: handleClose,
393
+ className: classes.cancelButton,
394
+ color: "inherit",
395
+ children: t("common.cancel")
396
+ }
397
+ )
398
+ ]
399
+ }
400
+ )
380
401
  ]
381
402
  }
382
403
  );