@cognizant-ai-lab/ui-common 1.3.3

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 (108) hide show
  1. package/dist/components/AgentChat/ChatCommon.d.ts +94 -0
  2. package/dist/components/AgentChat/ChatCommon.js +581 -0
  3. package/dist/components/AgentChat/ControlButtons.d.ts +16 -0
  4. package/dist/components/AgentChat/ControlButtons.js +24 -0
  5. package/dist/components/AgentChat/FormattedMarkdown.d.ts +32 -0
  6. package/dist/components/AgentChat/FormattedMarkdown.js +82 -0
  7. package/dist/components/AgentChat/Greetings.d.ts +1 -0
  8. package/dist/components/AgentChat/Greetings.js +38 -0
  9. package/dist/components/AgentChat/LlmChatButton.d.ts +12 -0
  10. package/dist/components/AgentChat/LlmChatButton.js +33 -0
  11. package/dist/components/AgentChat/SendButton.d.ts +12 -0
  12. package/dist/components/AgentChat/SendButton.js +28 -0
  13. package/dist/components/AgentChat/SyntaxHighlighterThemes.d.ts +14 -0
  14. package/dist/components/AgentChat/SyntaxHighlighterThemes.js +27 -0
  15. package/dist/components/AgentChat/Types.d.ts +17 -0
  16. package/dist/components/AgentChat/Types.js +26 -0
  17. package/dist/components/AgentChat/UserQueryDisplay.d.ts +5 -0
  18. package/dist/components/AgentChat/UserQueryDisplay.js +33 -0
  19. package/dist/components/AgentChat/Utils.d.ts +11 -0
  20. package/dist/components/AgentChat/Utils.js +64 -0
  21. package/dist/components/AgentChat/VoiceChat/MicrophoneButton.d.ts +29 -0
  22. package/dist/components/AgentChat/VoiceChat/MicrophoneButton.js +55 -0
  23. package/dist/components/AgentChat/VoiceChat/VoiceChat.d.ts +33 -0
  24. package/dist/components/AgentChat/VoiceChat/VoiceChat.js +180 -0
  25. package/dist/components/Authentication/Auth.d.ts +14 -0
  26. package/dist/components/Authentication/Auth.js +58 -0
  27. package/dist/components/ChatBot/ChatBot.d.ts +20 -0
  28. package/dist/components/ChatBot/ChatBot.js +75 -0
  29. package/dist/components/Common/Breadcrumbs.d.ts +6 -0
  30. package/dist/components/Common/Breadcrumbs.js +36 -0
  31. package/dist/components/Common/LlmChatOptionsButton.d.ts +9 -0
  32. package/dist/components/Common/LlmChatOptionsButton.js +31 -0
  33. package/dist/components/Common/LoadingSpinner.d.ts +10 -0
  34. package/dist/components/Common/LoadingSpinner.js +24 -0
  35. package/dist/components/Common/MUIAccordion.d.ts +17 -0
  36. package/dist/components/Common/MUIAccordion.js +76 -0
  37. package/dist/components/Common/MUIAlert.d.ts +11 -0
  38. package/dist/components/Common/MUIAlert.js +41 -0
  39. package/dist/components/Common/MUIDialog.d.ts +16 -0
  40. package/dist/components/Common/MUIDialog.js +40 -0
  41. package/dist/components/Common/Navbar.d.ts +15 -0
  42. package/dist/components/Common/Navbar.js +137 -0
  43. package/dist/components/Common/PageLoader.d.ts +5 -0
  44. package/dist/components/Common/PageLoader.js +26 -0
  45. package/dist/components/Common/Snackbar.d.ts +5 -0
  46. package/dist/components/Common/Snackbar.js +84 -0
  47. package/dist/components/Common/confirmationModal.d.ts +14 -0
  48. package/dist/components/Common/confirmationModal.js +65 -0
  49. package/dist/components/Common/notification.d.ts +18 -0
  50. package/dist/components/Common/notification.js +79 -0
  51. package/dist/components/ErrorPage/ErrorBoundary.d.ts +38 -0
  52. package/dist/components/ErrorPage/ErrorBoundary.js +77 -0
  53. package/dist/components/ErrorPage/ErrorPage.d.ts +12 -0
  54. package/dist/components/ErrorPage/ErrorPage.js +46 -0
  55. package/dist/components/MultiAgentAccelerator/AgentFlow.d.ts +21 -0
  56. package/dist/components/MultiAgentAccelerator/AgentFlow.js +394 -0
  57. package/dist/components/MultiAgentAccelerator/AgentNode.d.ts +18 -0
  58. package/dist/components/MultiAgentAccelerator/AgentNode.js +129 -0
  59. package/dist/components/MultiAgentAccelerator/GraphLayouts.d.ts +33 -0
  60. package/dist/components/MultiAgentAccelerator/GraphLayouts.js +297 -0
  61. package/dist/components/MultiAgentAccelerator/MultiAgentAccelerator.d.ts +17 -0
  62. package/dist/components/MultiAgentAccelerator/MultiAgentAccelerator.js +208 -0
  63. package/dist/components/MultiAgentAccelerator/PlasmaEdge.d.ts +3 -0
  64. package/dist/components/MultiAgentAccelerator/PlasmaEdge.js +124 -0
  65. package/dist/components/MultiAgentAccelerator/Sidebar.d.ts +12 -0
  66. package/dist/components/MultiAgentAccelerator/Sidebar.js +204 -0
  67. package/dist/components/MultiAgentAccelerator/ThoughtBubbleEdge.d.ts +12 -0
  68. package/dist/components/MultiAgentAccelerator/ThoughtBubbleEdge.js +15 -0
  69. package/dist/components/MultiAgentAccelerator/ThoughtBubbleOverlay.d.ts +11 -0
  70. package/dist/components/MultiAgentAccelerator/ThoughtBubbleOverlay.js +466 -0
  71. package/dist/components/MultiAgentAccelerator/const.d.ts +7 -0
  72. package/dist/components/MultiAgentAccelerator/const.js +39 -0
  73. package/dist/const.d.ts +10 -0
  74. package/dist/const.js +30 -0
  75. package/dist/controller/agent/Agent.d.ts +56 -0
  76. package/dist/controller/agent/Agent.js +162 -0
  77. package/dist/controller/llm/LlmChat.d.ts +18 -0
  78. package/dist/controller/llm/LlmChat.js +65 -0
  79. package/dist/controller/llm/endpoints.d.ts +1 -0
  80. package/dist/controller/llm/endpoints.js +17 -0
  81. package/dist/generated/neuro-san/NeuroSanClient.d.ts +413 -0
  82. package/dist/generated/neuro-san/NeuroSanClient.js +28 -0
  83. package/dist/index.d.ts +37 -0
  84. package/dist/index.js +52 -0
  85. package/dist/state/UserInfo.d.ts +16 -0
  86. package/dist/state/UserInfo.js +27 -0
  87. package/dist/state/environment.d.ts +18 -0
  88. package/dist/state/environment.js +33 -0
  89. package/dist/tsconfig.build.tsbuildinfo +1 -0
  90. package/dist/utils/Authentication.d.ts +31 -0
  91. package/dist/utils/Authentication.js +94 -0
  92. package/dist/utils/BrowserNavigation.d.ts +5 -0
  93. package/dist/utils/BrowserNavigation.js +22 -0
  94. package/dist/utils/Theme.d.ts +7 -0
  95. package/dist/utils/Theme.js +7 -0
  96. package/dist/utils/agentConversations.d.ts +24 -0
  97. package/dist/utils/agentConversations.js +113 -0
  98. package/dist/utils/text.d.ts +28 -0
  99. package/dist/utils/text.js +64 -0
  100. package/dist/utils/title.d.ts +1 -0
  101. package/dist/utils/title.js +20 -0
  102. package/dist/utils/types.d.ts +17 -0
  103. package/dist/utils/types.js +16 -0
  104. package/dist/utils/useLocalStorage.d.ts +1 -0
  105. package/dist/utils/useLocalStorage.js +55 -0
  106. package/dist/utils/zIndexLayers.d.ts +2 -0
  107. package/dist/utils/zIndexLayers.js +29 -0
  108. package/package.json +69 -0
@@ -0,0 +1,40 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /*
3
+ Copyright 2025 Cognizant Technology Solutions Corp, www.cognizant.com.
4
+
5
+ Licensed under the Apache License, Version 2.0 (the "License");
6
+ you may not use this file except in compliance with the License.
7
+ You may obtain a copy of the License at
8
+
9
+ http://www.apache.org/licenses/LICENSE-2.0
10
+
11
+ Unless required by applicable law or agreed to in writing, software
12
+ distributed under the License is distributed on an "AS IS" BASIS,
13
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ See the License for the specific language governing permissions and
15
+ limitations under the License.
16
+ */
17
+ import CloseIcon from "@mui/icons-material/Close";
18
+ import { styled } from "@mui/material";
19
+ import Dialog from "@mui/material/Dialog";
20
+ import DialogActions from "@mui/material/DialogActions";
21
+ import DialogContent from "@mui/material/DialogContent";
22
+ import DialogTitle from "@mui/material/DialogTitle";
23
+ import IconButton from "@mui/material/IconButton";
24
+ // #region: Styled Components
25
+ const StyledDialogTitle = styled(DialogTitle)({
26
+ fontSize: "1rem",
27
+ maxWidth: "580px",
28
+ paddingBottom: "0",
29
+ overflow: "hidden",
30
+ textOverflow: "ellipsis",
31
+ whiteSpace: "nowrap",
32
+ });
33
+ // #endregion: Types
34
+ export const MUIDialog = ({ children, className, closeable = true, contentSx, footer, id, isOpen, onClose, paperProps, title, }) => (_jsxs(Dialog, { "data-testid": id, id: id, onClose: onClose, open: isOpen, className: className, slotProps: {
35
+ paper: { sx: paperProps },
36
+ }, children: [_jsx(StyledDialogTitle, { id: `${id}-title`, children: title }), closeable && (_jsx(IconButton, { "aria-label": "close", id: `${id}-close-icon-btn`, onClick: onClose, sx: {
37
+ position: "absolute",
38
+ right: 8,
39
+ top: 8,
40
+ }, children: _jsx(CloseIcon, { "data-testid": `${id}-close-icon`, id: `${id}-close-icon`, sx: { color: "var(--bs-gray-medium)", fontSize: "1rem" } }) })), _jsx(DialogContent, { id: `${id}-content`, sx: contentSx, children: children }), _jsx(DialogActions, { id: `${id}-footer`, sx: { padding: "10px" }, children: footer })] }));
@@ -0,0 +1,15 @@
1
+ import { JSX as ReactJSX } from "react";
2
+ export interface NavbarProps {
3
+ readonly id: string;
4
+ readonly logo: string;
5
+ readonly query: Record<string, string | string[]>;
6
+ readonly pathname: string;
7
+ readonly userInfo: {
8
+ name: string;
9
+ image: string;
10
+ };
11
+ readonly authenticationType: string;
12
+ readonly signOut: () => void;
13
+ readonly supportEmailAddress: string;
14
+ }
15
+ export declare const Navbar: ({ authenticationType, id, logo, pathname, query, signOut, supportEmailAddress, userInfo, }: NavbarProps) => ReactJSX.Element;
@@ -0,0 +1,137 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /*
3
+ Copyright 2025 Cognizant Technology Solutions Corp, www.cognizant.com.
4
+
5
+ Licensed under the Apache License, Version 2.0 (the "License");
6
+ you may not use this file except in compliance with the License.
7
+ You may obtain a copy of the License at
8
+
9
+ http://www.apache.org/licenses/LICENSE-2.0
10
+
11
+ Unless required by applicable law or agreed to in writing, software
12
+ distributed under the License is distributed on an "AS IS" BASIS,
13
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ See the License for the specific language governing permissions and
15
+ limitations under the License.
16
+ */
17
+ /**
18
+ * Main navigation bar that appears at the top of each page
19
+ */
20
+ import ArrowDropDownIcon from "@mui/icons-material/ArrowDropDown";
21
+ import DarkModeIcon from "@mui/icons-material/DarkMode";
22
+ import { IconButton, Menu, MenuItem, Tooltip, Typography, useColorScheme } from "@mui/material";
23
+ import Grid from "@mui/material/Grid";
24
+ import { useEffect, useState } from "react";
25
+ import { ConfirmationModal } from "./confirmationModal.js";
26
+ import { LoadingSpinner } from "./LoadingSpinner.js";
27
+ import { authenticationEnabled, CONTACT_US_CONFIRMATION_DIALOG_TEXT, CONTACT_US_CONFIRMATION_DIALOG_TITLE, DEFAULT_USER_IMAGE, NEURO_SAN_UI_VERSION, } from "../../const.js";
28
+ import { navigateToUrl } from "../../utils/BrowserNavigation.js";
29
+ import { isDarkMode } from "../../utils/Theme.js";
30
+ const MENU_ITEM_TEXT_PROPS = {
31
+ color: "var(--bs-white)",
32
+ backgroundColor: "var(--bs-primary)",
33
+ fontFamily: "var(--bs-body-font-family)",
34
+ fontSize: "18px",
35
+ };
36
+ const DISABLE_OUTLINE_PROPS = {
37
+ outline: "none",
38
+ "&:focus": {
39
+ outline: "none",
40
+ },
41
+ "&:active": {
42
+ outline: "none",
43
+ },
44
+ };
45
+ export const Navbar = ({ authenticationType, id, logo, pathname, query, signOut, supportEmailAddress, userInfo, }) => {
46
+ // For email dialog
47
+ const [emailDialogOpen, setEmailDialogOpen] = useState(false);
48
+ // Dark mode
49
+ const { mode, setMode, systemMode } = useColorScheme();
50
+ const darkMode = isDarkMode(mode, systemMode);
51
+ // Gate to make sure we only attempt to render after Next.js has completed its rehydration
52
+ const [hydrated, setHydrated] = useState(false);
53
+ useEffect(() => {
54
+ // Indicate that the component has been hydrated
55
+ setHydrated(true);
56
+ }, []);
57
+ // Help menu wiring
58
+ const [helpMenuAnchorEl, setHelpMenuAnchorEl] = useState(null);
59
+ const helpMenuOpen = Boolean(helpMenuAnchorEl);
60
+ const handleCloseHelpMenu = () => {
61
+ setHelpMenuAnchorEl(null);
62
+ };
63
+ // User menu wiring
64
+ const [userMenuAnchorEl, setUserMenuAnchorEl] = useState(null);
65
+ const userMenuOpen = Boolean(userMenuAnchorEl);
66
+ const handleCloseUserMenu = () => {
67
+ setUserMenuAnchorEl(null);
68
+ };
69
+ // Explore menu wiring
70
+ const [exploreMenuAnchorEl, setExploreMenuAnchorEl] = useState(null);
71
+ const exploreMenuOpen = Boolean(exploreMenuAnchorEl);
72
+ const handleCloseExploreMenu = () => {
73
+ setExploreMenuAnchorEl(null);
74
+ };
75
+ return hydrated ? (_jsxs(Grid, { id: "nav-bar-container", container: true, alignItems: "center", sx: {
76
+ ...MENU_ITEM_TEXT_PROPS,
77
+ color: "var(--bs-white)",
78
+ padding: "0.25rem",
79
+ }, children: [_jsx("a", { id: "splash-logo-link", href: "https://www.cognizant.com/us/en", style: {
80
+ display: "flex",
81
+ paddingLeft: "0.15rem",
82
+ }, target: "_blank", rel: "noopener noreferrer", children: _jsx("img", { id: "logo-img", width: "200", height: "45", src: "/cognizant-logo-white.svg", alt: "Cognizant Logo" }) }), _jsx(Grid, { id: id, children: _jsx(Typography, { id: "nav-bar-brand", sx: {
83
+ ...MENU_ITEM_TEXT_PROPS,
84
+ color: "var(--bs-white)",
85
+ marginLeft: "0.85rem",
86
+ fontSize: "16px",
87
+ fontWeight: "bold",
88
+ }, children: _jsxs("a", { id: "navbar-brand-link", style: {
89
+ fontWeight: 500,
90
+ fontSize: "1.1rem",
91
+ color: "var(--bs-white)",
92
+ position: "relative",
93
+ bottom: "1px",
94
+ textDecoration: "none",
95
+ }, href: Object.keys(query || {}).length > 0
96
+ ? `/?${new URLSearchParams(query).toString()}`
97
+ : "/", children: [logo, " ", pathname === "/multiAgentAccelerator" ? "Multi-Agent Accelerator" : "Decisioning"] }) }) }), _jsx(Grid, { id: "build", sx: {
98
+ flex: 1, // Take available space
99
+ display: "flex",
100
+ justifyContent: "flex-end", // Right align
101
+ alignItems: "center", // Vertically center
102
+ color: "var(--bs-white)",
103
+ marginRight: "50px",
104
+ }, children: _jsxs(Typography, { id: "build-text", sx: { ...MENU_ITEM_TEXT_PROPS }, children: ["Build: ", _jsx("strong", { id: "build-strong", children: NEURO_SAN_UI_VERSION })] }) }), _jsxs(Grid, { id: "explore-dropdown", sx: { cursor: "pointer", marginRight: "30px" }, children: [_jsxs(Typography, { id: "explore-toggle", sx: {
105
+ ...MENU_ITEM_TEXT_PROPS,
106
+ display: "flex",
107
+ alignItems: "center",
108
+ }, onClick: (event) => {
109
+ setExploreMenuAnchorEl(event.currentTarget);
110
+ }, children: ["Explore", _jsx(ArrowDropDownIcon, { id: "nav-explore-dropdown-arrow", sx: { color: "var(--bs-white)", fontSize: 22 } })] }), _jsxs(Menu, { id: "explore-menu", anchorEl: exploreMenuAnchorEl, open: exploreMenuOpen, onClose: handleCloseExploreMenu, children: [_jsx(MenuItem, { id: "explore-neuro-san-studio", component: "a", href: "https://github.com/cognizant-ai-lab/neuro-san-studio", target: "_blank", sx: { ...DISABLE_OUTLINE_PROPS }, children: "Neuro-san studio (examples)" }, "explore-neuro-san-studio"), _jsx(MenuItem, { id: "explore-neuro-san", component: "a", href: "https://github.com/cognizant-ai-lab/neuro-san", target: "_blank", sx: { ...DISABLE_OUTLINE_PROPS }, children: "Neuro-san (core)" }, "explore-neuro-san")] })] }), _jsxs(Grid, { id: "help-dropdown", sx: { cursor: "pointer", marginRight: "30px" }, children: [_jsxs(Typography, { id: "help-toggle", sx: {
111
+ ...MENU_ITEM_TEXT_PROPS,
112
+ display: "flex",
113
+ alignItems: "center",
114
+ }, onClick: (event) => {
115
+ setHelpMenuAnchorEl(event.currentTarget);
116
+ }, children: ["Help", _jsx(ArrowDropDownIcon, { id: "nav-help-dropdown-arrow", sx: { color: "var(--bs-white)", fontSize: 22 } })] }), _jsxs(Menu, { id: "help-menu", anchorEl: helpMenuAnchorEl, open: helpMenuOpen, onClose: handleCloseHelpMenu, children: [_jsx(MenuItem, { id: "user-guide", component: "a", href: "/userguide", target: "_blank", sx: { ...DISABLE_OUTLINE_PROPS }, children: "User guide" }, "user-guide"), _jsx(MenuItem, { href: null, id: "contact-us-help", onClick: () => setEmailDialogOpen(true), children: "Contact Us" }, "contact-us-help")] })] }), emailDialogOpen ? (_jsx(ConfirmationModal, { id: "email-dialog", content: CONTACT_US_CONFIRMATION_DIALOG_TEXT, handleCancel: () => {
117
+ setEmailDialogOpen(false);
118
+ }, handleOk: () => {
119
+ navigateToUrl(`mailto:${supportEmailAddress}`);
120
+ setEmailDialogOpen(false);
121
+ }, title: CONTACT_US_CONFIRMATION_DIALOG_TITLE })) : null, userInfo ? (_jsxs(Grid, { id: "user-dropdown", children: [_jsxs(IconButton, { "aria-label": "User dropdown toggle", id: "user-dropdown-toggle", onClick: (event) => {
122
+ setUserMenuAnchorEl(event.currentTarget);
123
+ }, sx: {
124
+ ...MENU_ITEM_TEXT_PROPS,
125
+ }, children: [_jsx("img", { id: "user-image", src: userInfo.image || DEFAULT_USER_IMAGE, width: 30, height: 30, title: userInfo.name, alt: "" }), _jsx(ArrowDropDownIcon, { id: "nav-user-dropdown-arrow", sx: { color: "var(--bs-white)", fontSize: 22 } })] }), _jsxs(Menu, { id: "user-menu", anchorEl: userMenuAnchorEl, open: userMenuOpen, onClose: handleCloseUserMenu, children: [_jsx(MenuItem, { id: "user-signed-in-as", disabled: true, sx: { fontWeight: "bold" }, children: "Signed in as" }), _jsx(MenuItem, { id: "user-name", disabled: true, sx: {
126
+ whiteSpace: "normal",
127
+ wordWrap: "break-word",
128
+ fontSize: "smaller",
129
+ }, children: userInfo.name }), _jsx(MenuItem, { id: "auth-type-title", disabled: true, sx: { fontWeight: "bold" }, children: "Authentication" }), _jsx(MenuItem, { id: "authentication-type-menu-item", disabled: true, sx: { fontSize: "smaller" }, children: authenticationType }), authenticationEnabled() && (_jsx(MenuItem, { id: "user-sign-out", sx: { ...DISABLE_OUTLINE_PROPS, fontWeight: "bold" }, onClick: signOut, children: "Sign out" }))] })] })) : null, _jsx(Tooltip, { id: "dark-mode-toggle", title: "Toggle dark mode", children: _jsx(DarkModeIcon, { id: "dark-mode-icon", sx: {
130
+ marginRight: "1rem",
131
+ fontSize: "1rem",
132
+ cursor: "pointer",
133
+ color: darkMode ? "var(--bs-yellow)" : "var(--bs-gray-dark)",
134
+ }, onClick: () => {
135
+ setMode(darkMode ? "light" : "dark");
136
+ } }) })] })) : (_jsx(LoadingSpinner, { id: "navbar-loading-spinner" }));
137
+ };
@@ -0,0 +1,5 @@
1
+ interface PageLoaderProps {
2
+ id: string;
3
+ }
4
+ export declare const PageLoader: ({ id }: PageLoaderProps) => import("react/jsx-runtime").JSX.Element;
5
+ export {};
@@ -0,0 +1,26 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /*
3
+ Copyright 2025 Cognizant Technology Solutions Corp, www.cognizant.com.
4
+
5
+ Licensed under the Apache License, Version 2.0 (the "License");
6
+ you may not use this file except in compliance with the License.
7
+ You may obtain a copy of the License at
8
+
9
+ http://www.apache.org/licenses/LICENSE-2.0
10
+
11
+ Unless required by applicable law or agreed to in writing, software
12
+ distributed under the License is distributed on an "AS IS" BASIS,
13
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ See the License for the specific language governing permissions and
15
+ limitations under the License.
16
+ */
17
+ import { CircularProgress, Typography } from "@mui/material";
18
+ export const PageLoader = ({ id }) => (_jsxs("div", { id: `${id}__loader`, style: {
19
+ left: "0",
20
+ position: "absolute",
21
+ right: "0",
22
+ textAlign: "center",
23
+ top: "50%",
24
+ }, children: [_jsx(Typography, { id: `${id}-loader__message`, variant: "h3", children: "Loading... Please wait" }), _jsx(CircularProgress, { id: `${id}-loader__spinner`, sx: {
25
+ color: "var(--bs-primary)",
26
+ }, size: "100px" })] }));
@@ -0,0 +1,5 @@
1
+ import { CustomContentProps } from "notistack";
2
+ export interface SnackbarProps extends CustomContentProps {
3
+ description: string;
4
+ }
5
+ export declare const Snackbar: import("react").ForwardRefExoticComponent<SnackbarProps & import("react").RefAttributes<HTMLDivElement>>;
@@ -0,0 +1,84 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /*
3
+ Copyright 2025 Cognizant Technology Solutions Corp, www.cognizant.com.
4
+
5
+ Licensed under the Apache License, Version 2.0 (the "License");
6
+ you may not use this file except in compliance with the License.
7
+ You may obtain a copy of the License at
8
+
9
+ http://www.apache.org/licenses/LICENSE-2.0
10
+
11
+ Unless required by applicable law or agreed to in writing, software
12
+ distributed under the License is distributed on an "AS IS" BASIS,
13
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ See the License for the specific language governing permissions and
15
+ limitations under the License.
16
+ */
17
+ import CloseIcon from "@mui/icons-material/Close";
18
+ import { styled, useColorScheme } from "@mui/material";
19
+ import Box from "@mui/material/Box";
20
+ import IconButton from "@mui/material/IconButton";
21
+ import { SnackbarContent, useSnackbar } from "notistack";
22
+ import { forwardRef } from "react";
23
+ import { isDarkMode } from "../../utils/Theme.js";
24
+ // #region: Styled Components
25
+ const IconBox = styled(Box)({
26
+ position: "relative",
27
+ bottom: "2px",
28
+ "&.success": {
29
+ color: "var(--bs-success)",
30
+ },
31
+ "&.error": {
32
+ color: "var(--bs-danger)",
33
+ },
34
+ "&.warning": {
35
+ color: "var(--bs-warning)",
36
+ },
37
+ "&.info": {
38
+ color: "var(--bs-info)",
39
+ },
40
+ });
41
+ // #endregion: Types
42
+ // Passing Snackbar callback as a function because if we use an arrow function here we'd have to set displayName
43
+ export const Snackbar = forwardRef(
44
+ // eslint-disable-next-line prefer-arrow-callback
45
+ function Snackbar({ description, hideIconVariant = false, iconVariant, id, message, variant }, ref) {
46
+ const { closeSnackbar } = useSnackbar();
47
+ const handleCloseSnackbar = () => closeSnackbar(id);
48
+ const icon = iconVariant[variant];
49
+ const { mode, systemMode } = useColorScheme();
50
+ const darkMode = isDarkMode(mode, systemMode);
51
+ // Temporary styling for implementation of dark mode
52
+ const darkModeStyling = {
53
+ backgroundColor: darkMode ? "var(--bs-dark-mode-dim)" : "var(--bs-white)",
54
+ color: darkMode ? "var(--bs-white)" : "var(--bs-primary)",
55
+ };
56
+ return (_jsx(SnackbarContent, { ref: ref, role: "alert", children: _jsxs(Box, { className: `${variant}-snackbar-notification`, id: `${id}-snackbar-box`, sx: {
57
+ ...darkModeStyling,
58
+ borderColor: "transparent",
59
+ borderRadius: "var(--bs-border-radius)",
60
+ borderWidth: "1px",
61
+ boxShadow: `0 6px 16px 0 rgba(0, 0, 0, 0.08), 0 3px 6px -4px rgba(0, 0, 0, 0.12),
62
+ 0 9px 28px 8px rgba(0, 0, 0, 0.05)`,
63
+ maxWidth: "450px",
64
+ minWidth: "250px",
65
+ padding: "0.9rem",
66
+ }, children: [!hideIconVariant && (_jsx(Box, { id: `${id}-snackbar-icon-box-container`, sx: { display: "inline-flex", flexDirection: "column" }, children: _jsx(IconBox, { className: variant, "data-testid": `${id}-snackbar-icon-box`, id: `${id}-snackbar-icon-box`, children: icon }) })), _jsxs(Box, { id: `${id}-snackbar-content-box`, sx: {
67
+ display: "inline-flex",
68
+ flexDirection: "column",
69
+ width: "88%",
70
+ wordWrap: "break-word",
71
+ }, children: [_jsx(Box, { id: `${id}-snackbar-message-box`, sx: {
72
+ display: "block",
73
+ // If no description, this is the only message, so reduce font size
74
+ fontSize: description ? "0.95rem" : "0.85rem",
75
+ paddingRight: "25px",
76
+ }, children: message }), _jsx(IconButton, { "aria-label": "close", id: `${id}-close-icon-btn`, onClick: handleCloseSnackbar, sx: {
77
+ position: "absolute",
78
+ right: 4,
79
+ top: 4,
80
+ }, children: _jsx(CloseIcon, { "data-testid": `${id}-close-icon`, id: `${id}-close-icon`, sx: {
81
+ color: "var(--bs-gray-medium)",
82
+ fontSize: "0.6em",
83
+ } }) }), description && (_jsx(Box, { id: `${id}-snackbar-description-box`, sx: { fontSize: "0.8rem", paddingTop: "10px", paddingBottom: "10px" }, children: description }))] })] }) }));
84
+ });
@@ -0,0 +1,14 @@
1
+ import { FC, ReactNode } from "react";
2
+ interface ConfirmationModalProps {
3
+ cancelBtnLabel?: string;
4
+ closeable?: boolean;
5
+ content: ReactNode;
6
+ handleCancel?: () => void;
7
+ handleOk?: () => void;
8
+ id: string;
9
+ maskCloseable?: boolean;
10
+ okBtnLabel?: string;
11
+ title: ReactNode;
12
+ }
13
+ export declare const ConfirmationModal: FC<ConfirmationModalProps>;
14
+ export {};
@@ -0,0 +1,65 @@
1
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /*
3
+ Copyright 2025 Cognizant Technology Solutions Corp, www.cognizant.com.
4
+
5
+ Licensed under the Apache License, Version 2.0 (the "License");
6
+ you may not use this file except in compliance with the License.
7
+ You may obtain a copy of the License at
8
+
9
+ http://www.apache.org/licenses/LICENSE-2.0
10
+
11
+ Unless required by applicable law or agreed to in writing, software
12
+ distributed under the License is distributed on an "AS IS" BASIS,
13
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ See the License for the specific language governing permissions and
15
+ limitations under the License.
16
+ */
17
+ import { styled } from "@mui/material";
18
+ import Box from "@mui/material/Box";
19
+ import Button from "@mui/material/Button";
20
+ import { useState } from "react";
21
+ import { MUIDialog } from "./MUIDialog.js";
22
+ // #region: Styled Components
23
+ const StyledButton = styled(Button)({
24
+ fontSize: "0.8em",
25
+ padding: "0px 7px",
26
+ });
27
+ const StyledOKButton = styled(StyledButton)(({ disabled }) => ({
28
+ backgroundColor: disabled ? "rgba(0, 0, 0, 0.12) !important" : "var(--bs-primary) !important",
29
+ }));
30
+ // #endregion: Types
31
+ export const ConfirmationModal = ({ cancelBtnLabel, closeable = true, content = "", handleCancel = null, handleOk = null, id = "", maskCloseable = false, okBtnLabel, title = "", }) => {
32
+ const [modalOpen, setModalOpen] = useState(true);
33
+ const [isLoading, setIsLoading] = useState(false);
34
+ const handleCloseWrapper = (_event, reason) => {
35
+ // Prevent closing on click of gray background mask
36
+ if (!maskCloseable && reason === "backdropClick") {
37
+ return;
38
+ }
39
+ handleCancel?.(); // call handleCancel if it's not null
40
+ setModalOpen(false);
41
+ };
42
+ const handleOKWrapper = async () => {
43
+ try {
44
+ if (handleOk) {
45
+ setIsLoading(true);
46
+ handleOk();
47
+ }
48
+ }
49
+ finally {
50
+ setModalOpen(false);
51
+ setIsLoading(false);
52
+ }
53
+ };
54
+ const Footer = (_jsxs(_Fragment, { children: [handleCancel && ( // If there is no handleCancel passed, Cancel button will not be rendered
55
+ _jsx(StyledButton
56
+ // This ID needs to be dynamic because there can be several instances of this on the page
57
+ , {
58
+ // This ID needs to be dynamic because there can be several instances of this on the page
59
+ id: `${id}-confirm-cancel-btn`, onClick: () => handleCloseWrapper(), disabled: isLoading, variant: "outlined", children: cancelBtnLabel ?? "Cancel" }, "confirm-cancel")), _jsx(StyledOKButton
60
+ // This ID needs to be dynamic because there can be several instances of this on the page
61
+ , {
62
+ // This ID needs to be dynamic because there can be several instances of this on the page
63
+ id: `${id}-confirm-ok-btn`, disabled: isLoading, onClick: () => handleOKWrapper(), variant: "contained", children: okBtnLabel ?? "Confirm" }, "confirm-ok")] }));
64
+ return (_jsx(MUIDialog, { closeable: closeable, contentSx: { fontSize: "0.8rem", minWidth: "550px", paddingTop: "0" }, footer: Footer, id: `${id}-confirm-main`, isOpen: modalOpen, onClose: (_event, reason) => handleCloseWrapper(_event, reason), title: title, children: _jsx(Box, { id: `${id}-confirm-content`, sx: { marginTop: "15px" }, children: content }) }));
65
+ };
@@ -0,0 +1,18 @@
1
+ import { SnackbarKey, SnackbarOrigin } from "notistack";
2
+ import { JSX as ReactJSX } from "react";
3
+ export declare enum NotificationType {
4
+ "success" = 0,
5
+ "info" = 1,
6
+ "warning" = 2,
7
+ "error" = 3
8
+ }
9
+ export declare function closeNotification(snackbarId?: SnackbarKey): void;
10
+ /**
11
+ * Convenience method to allow sending notifications to user with a one-liner.
12
+ * Simply wraps @Notification function
13
+ * @param variantType Indicates whether it's error, warning, info etc.
14
+ * @param message Brief summary of the notification
15
+ * @param description More complete description of the notification
16
+ * @param placement Where to show notification. Defaults to top-right.
17
+ */
18
+ export declare function sendNotification(variantType: NotificationType, message: string, description?: string | ReactJSX.Element, placement?: SnackbarOrigin): void;
@@ -0,0 +1,79 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ /*
3
+ Copyright 2025 Cognizant Technology Solutions Corp, www.cognizant.com.
4
+
5
+ Licensed under the Apache License, Version 2.0 (the "License");
6
+ you may not use this file except in compliance with the License.
7
+ You may obtain a copy of the License at
8
+
9
+ http://www.apache.org/licenses/LICENSE-2.0
10
+
11
+ Unless required by applicable law or agreed to in writing, software
12
+ distributed under the License is distributed on an "AS IS" BASIS,
13
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ See the License for the specific language governing permissions and
15
+ limitations under the License.
16
+ */
17
+ import { closeSnackbar, enqueueSnackbar } from "notistack";
18
+ import { renderToString } from "react-dom/server";
19
+ export var NotificationType;
20
+ (function (NotificationType) {
21
+ NotificationType[NotificationType["success"] = 0] = "success";
22
+ NotificationType[NotificationType["info"] = 1] = "info";
23
+ NotificationType[NotificationType["warning"] = 2] = "warning";
24
+ NotificationType[NotificationType["error"] = 3] = "error";
25
+ })(NotificationType || (NotificationType = {}));
26
+ // Display warning and error notification popups for this many seconds
27
+ const ERROR_WARNING_NOTIFICATION_DURATION_MS = 15_000;
28
+ // Display info notification popups for this many seconds
29
+ const SUCCESS_NOTIFICATION_DURATION_MS = 5000;
30
+ export function closeNotification(snackbarId) {
31
+ closeSnackbar(snackbarId);
32
+ }
33
+ /**
34
+ * Convenience method to allow sending notifications to user with a one-liner.
35
+ * Simply wraps @Notification function
36
+ * @param variantType Indicates whether it's error, warning, info etc.
37
+ * @param message Brief summary of the notification
38
+ * @param description More complete description of the notification
39
+ * @param placement Where to show notification. Defaults to top-right.
40
+ */
41
+ export function sendNotification(variantType, message, description = "",
42
+ // eslint-disable-next-line unicorn/no-object-as-default-parameter
43
+ placement = {
44
+ vertical: "top",
45
+ horizontal: "right",
46
+ }) {
47
+ // Log a copy to the console for troubleshooting
48
+ const descriptionAsString = typeof description === "string" ? description : renderToString(description);
49
+ console.debug(`Notification: Message: "${message}" Description: "${descriptionAsString}"`);
50
+ // Show error and warnings for longer
51
+ let duration;
52
+ switch (variantType) {
53
+ case NotificationType.info:
54
+ case NotificationType.success:
55
+ duration = SUCCESS_NOTIFICATION_DURATION_MS;
56
+ break;
57
+ case NotificationType.warning:
58
+ case NotificationType.error:
59
+ default:
60
+ duration = ERROR_WARNING_NOTIFICATION_DURATION_MS;
61
+ break;
62
+ }
63
+ // Use some minor customization to be able to inject ids for testing
64
+ const messageForId = message
65
+ .replaceAll(" ", "-")
66
+ .replace(/[^a-zA-Z0-9-]/gu, "")
67
+ .toLowerCase();
68
+ const baseId = `notification-message-${messageForId}-${NotificationType[variantType]}`;
69
+ const messageSpan = _jsx("span", { id: `${baseId}-span`, children: message });
70
+ enqueueSnackbar(messageSpan, {
71
+ anchorOrigin: placement,
72
+ autoHideDuration: duration,
73
+ disableWindowBlurListener: true,
74
+ // @ts-expect-error - Could "declare module" to fix this
75
+ description,
76
+ key: baseId,
77
+ variant: NotificationType[variantType],
78
+ });
79
+ }
@@ -0,0 +1,38 @@
1
+ import { Component, ErrorInfo, ReactNode } from "react";
2
+ /**
3
+ * Interface to define the state for this component
4
+ */
5
+ interface ErrorBoundaryState {
6
+ readonly hasError: boolean;
7
+ readonly error: unknown;
8
+ }
9
+ /**
10
+ * Interface to define the incoming props for this component
11
+ */
12
+ interface ErrorBoundaryProps {
13
+ readonly id: string;
14
+ readonly children: ReactNode;
15
+ }
16
+ /**
17
+ * Implements a system-wide error handler for NextJS pages in our app.
18
+ * Taken from here: https://nextjs.org/docs/advanced-features/error-handling
19
+ *
20
+ * Note: as of writing (April 2023) ReactJS does not support error boundaries for functional components (like all of
21
+ * those in UniLEAF are) so we take the approach of wrapping all components in our app with this class component that
22
+ * handles the error boundary.
23
+ */
24
+ export declare class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> {
25
+ /**
26
+ * @public
27
+ * This is the key override called by ReactJS when an unhandled error is thrown. And this is why you cannot create
28
+ * error boundaries in functional components -- no way to override this method.
29
+ */
30
+ static getDerivedStateFromError(error: unknown): {
31
+ hasError: boolean;
32
+ error: unknown;
33
+ };
34
+ constructor(props: ErrorBoundaryProps);
35
+ componentDidCatch(error: unknown, errorInfo: ErrorInfo): void;
36
+ render(): string | number | boolean | Iterable<ReactNode> | import("react").PromiseLikeOfReactNode | import("react/jsx-runtime").JSX.Element;
37
+ }
38
+ export {};
@@ -0,0 +1,77 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ /*
3
+ Copyright 2025 Cognizant Technology Solutions Corp, www.cognizant.com.
4
+
5
+ Licensed under the Apache License, Version 2.0 (the "License");
6
+ you may not use this file except in compliance with the License.
7
+ You may obtain a copy of the License at
8
+
9
+ http://www.apache.org/licenses/LICENSE-2.0
10
+
11
+ Unless required by applicable law or agreed to in writing, software
12
+ distributed under the License is distributed on an "AS IS" BASIS,
13
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ See the License for the specific language governing permissions and
15
+ limitations under the License.
16
+ */
17
+ import { Component } from "react";
18
+ import ErrorPage from "./ErrorPage.js";
19
+ /**
20
+ * Implements a system-wide error handler for NextJS pages in our app.
21
+ * Taken from here: https://nextjs.org/docs/advanced-features/error-handling
22
+ *
23
+ * Note: as of writing (April 2023) ReactJS does not support error boundaries for functional components (like all of
24
+ * those in UniLEAF are) so we take the approach of wrapping all components in our app with this class component that
25
+ * handles the error boundary.
26
+ */
27
+ export class ErrorBoundary extends Component {
28
+ /**
29
+ * @public
30
+ * This is the key override called by ReactJS when an unhandled error is thrown. And this is why you cannot create
31
+ * error boundaries in functional components -- no way to override this method.
32
+ */
33
+ static getDerivedStateFromError(error) {
34
+ // Update state so the next render will show the fallback UI
35
+ return { hasError: true, error };
36
+ }
37
+ constructor(props) {
38
+ super(props);
39
+ // Define a state variable to track whether is an error or not
40
+ this.state = { hasError: false, error: null };
41
+ }
42
+ // No need for "this" here
43
+ // eslint-disable-next-line @typescript-eslint/class-methods-use-this
44
+ componentDidCatch(error, errorInfo) {
45
+ // TODO: Send this to central logging service once it's available
46
+ console.error({ error, errorInfo });
47
+ }
48
+ render() {
49
+ // Check if the error is thrown
50
+ if (this.state.hasError) {
51
+ // Render fallback UI
52
+ const id = this.props.id;
53
+ const error = this.state.error;
54
+ let fileName = "Unknown";
55
+ let lineNumber = null;
56
+ let columnNumber = null;
57
+ let message = "";
58
+ if (error instanceof Error) {
59
+ // the error object is an instance of the built-in Error type in JavaScript
60
+ const customError = error;
61
+ if (customError.fileName) {
62
+ fileName = customError.fileName;
63
+ }
64
+ if (customError.lineNumber != null) {
65
+ lineNumber = customError.lineNumber;
66
+ }
67
+ if (customError.columnNumber != null) {
68
+ columnNumber = customError.columnNumber;
69
+ }
70
+ message = customError.message;
71
+ }
72
+ return (_jsx(ErrorPage, { id: id, errorText: `${message} in ${fileName} line ${lineNumber} column ${columnNumber}` }));
73
+ }
74
+ // Return children components in case of no error
75
+ return this.props.children;
76
+ }
77
+ }
@@ -0,0 +1,12 @@
1
+ import { ReactElement } from "react";
2
+ interface ErrorPageProps {
3
+ id: string;
4
+ errorText: string;
5
+ }
6
+ /**
7
+ * This is the page that will be shown to users when the outer error boundary is triggered
8
+ * @param id HTML id for the <code>div</code> for this page
9
+ * @param errorText Error text to be displayed
10
+ */
11
+ export default function ErrorPage({ id, errorText }: ErrorPageProps): ReactElement;
12
+ export {};