@red-hat-developer-hub/backstage-plugin-intelligent-assistant 5.2.0 → 5.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.
- package/CHANGELOG.md +14 -0
- package/README.md +14 -2
- package/dist/alpha.d.ts +24 -0
- package/dist/components/LightSpeedChat.esm.js +74 -27
- package/dist/components/LightSpeedChat.esm.js.map +1 -1
- package/dist/components/LightspeedChatBoxHeader.esm.js +28 -0
- package/dist/components/LightspeedChatBoxHeader.esm.js.map +1 -1
- package/dist/components/LightspeedChatContainer.esm.js +2 -1
- package/dist/components/LightspeedChatContainer.esm.js.map +1 -1
- package/dist/components/LightspeedDrawerProvider.esm.js +1 -0
- package/dist/components/LightspeedDrawerProvider.esm.js.map +1 -1
- package/dist/components/MessageBarModelSelector.esm.js +104 -12
- package/dist/components/MessageBarModelSelector.esm.js.map +1 -1
- package/dist/components/ScreenContextChip.esm.js +172 -0
- package/dist/components/ScreenContextChip.esm.js.map +1 -0
- package/dist/hooks/screenContextLabelSubscription.esm.js +113 -0
- package/dist/hooks/screenContextLabelSubscription.esm.js.map +1 -0
- package/dist/hooks/useScreenContextLabelRevision.esm.js +13 -0
- package/dist/hooks/useScreenContextLabelRevision.esm.js.map +1 -0
- package/dist/hooks/useScreenContextSettings.esm.js +110 -0
- package/dist/hooks/useScreenContextSettings.esm.js.map +1 -0
- package/dist/hooks/useWindowLocation.esm.js +28 -0
- package/dist/hooks/useWindowLocation.esm.js.map +1 -0
- package/dist/translations/de.esm.js +24 -0
- package/dist/translations/de.esm.js.map +1 -1
- package/dist/translations/es.esm.js +24 -0
- package/dist/translations/es.esm.js.map +1 -1
- package/dist/translations/fr.esm.js +24 -0
- package/dist/translations/fr.esm.js.map +1 -1
- package/dist/translations/it.esm.js +24 -0
- package/dist/translations/it.esm.js.map +1 -1
- package/dist/translations/ja.esm.js +24 -0
- package/dist/translations/ja.esm.js.map +1 -1
- package/dist/translations/ref.esm.js +24 -0
- package/dist/translations/ref.esm.js.map +1 -1
- package/dist/utils/dom-selectors.esm.js +22 -2
- package/dist/utils/dom-selectors.esm.js.map +1 -1
- package/dist/utils/screen-capture.esm.js +116 -0
- package/dist/utils/screen-capture.esm.js.map +1 -0
- package/dist/utils/screen-context-utils.esm.js +343 -0
- package/dist/utils/screen-context-utils.esm.js.map +1 -0
- package/dist/utils/sensitive-data-redactor.esm.js +39 -1
- package/dist/utils/sensitive-data-redactor.esm.js.map +1 -1
- package/package.json +3 -3
|
@@ -41,6 +41,9 @@ const LightspeedChatBoxHeader = ({
|
|
|
41
41
|
onPinnedChatsToggle,
|
|
42
42
|
isSavedPromptsEnabled,
|
|
43
43
|
onSavedPromptsToggle,
|
|
44
|
+
screenContextAdminEnabled = false,
|
|
45
|
+
isScreenContextSharingEnabled = false,
|
|
46
|
+
onScreenContextSharingToggle,
|
|
44
47
|
onMcpSettingsClick,
|
|
45
48
|
isModelSelectorDisabled = false,
|
|
46
49
|
hideModelSelector = false,
|
|
@@ -215,6 +218,31 @@ const LightspeedChatBoxHeader = ({
|
|
|
215
218
|
},
|
|
216
219
|
"enableSavedPrompts"
|
|
217
220
|
),
|
|
221
|
+
screenContextAdminEnabled && (isScreenContextSharingEnabled ? /* @__PURE__ */ jsx(
|
|
222
|
+
DropdownItem,
|
|
223
|
+
{
|
|
224
|
+
value: "disableScreenContext",
|
|
225
|
+
icon: /* @__PURE__ */ jsx(ToggleOnOutlinedIcon, { sx: { marginTop: "8px" } }),
|
|
226
|
+
description: t(
|
|
227
|
+
"settings.screenContext.enabled.description"
|
|
228
|
+
),
|
|
229
|
+
onClick: () => onScreenContextSharingToggle?.(false),
|
|
230
|
+
children: t("settings.screenContext.disable")
|
|
231
|
+
},
|
|
232
|
+
"disableScreenContext"
|
|
233
|
+
) : /* @__PURE__ */ jsx(
|
|
234
|
+
DropdownItem,
|
|
235
|
+
{
|
|
236
|
+
value: "enableScreenContext",
|
|
237
|
+
icon: /* @__PURE__ */ jsx(ToggleOffOutlinedIcon, { sx: { marginTop: "8px" } }),
|
|
238
|
+
description: t(
|
|
239
|
+
"settings.screenContext.disabled.description"
|
|
240
|
+
),
|
|
241
|
+
onClick: () => onScreenContextSharingToggle?.(true),
|
|
242
|
+
children: t("settings.screenContext.enable")
|
|
243
|
+
},
|
|
244
|
+
"enableScreenContext"
|
|
245
|
+
)),
|
|
218
246
|
/* @__PURE__ */ jsxs(
|
|
219
247
|
DropdownItem,
|
|
220
248
|
{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LightspeedChatBoxHeader.esm.js","sources":["../../src/components/LightspeedChatBoxHeader.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 { Ref, useState } from 'react';\n\nimport ToggleOffOutlinedIcon from '@mui/icons-material/ToggleOffOutlined';\nimport ToggleOnOutlinedIcon from '@mui/icons-material/ToggleOnOutlined';\nimport Divider from '@mui/material/Divider';\nimport { styled } from '@mui/material/styles';\nimport {\n ChatbotDisplayMode,\n ChatbotHeaderActions,\n ChatbotHeaderOptionsDropdown,\n} from '@patternfly/chatbot';\nimport {\n Dropdown,\n DropdownGroup,\n DropdownItem,\n DropdownList,\n Icon,\n Label,\n MenuToggle,\n MenuToggleElement,\n} from '@patternfly/react-core';\nimport {\n ExpandIcon,\n OpenDrawerRightIcon,\n OutlinedWindowRestoreIcon,\n RhUiEllipsisVerticalFillIcon,\n} from '@patternfly/react-icons';\n\nimport { useTranslation } from '../hooks/useTranslation';\nimport { McpSettingsIcon } from './McpSettingsIcon';\n\ntype LightspeedChatBoxHeaderProps = {\n displayMode: ChatbotDisplayMode;\n selectedModel: string;\n handleSelectedModel: (item: string) => void;\n models: { label: string; value: string; provider: string }[];\n isPinningChatsEnabled: boolean;\n onPinnedChatsToggle: (state: boolean) => void;\n isSavedPromptsEnabled: boolean;\n onSavedPromptsToggle: (state: boolean) => void;\n onMcpSettingsClick: () => void;\n isModelSelectorDisabled?: boolean;\n hideModelSelector?: boolean;\n /** When false, omits pinned-chats and MCP entries (Chat tab only). */\n showChatTabOptions?: boolean;\n /** When false, shows prompt-only settings label and opens saved-prompts tab. */\n showMcpSettings?: boolean;\n setDisplayMode: (mode: ChatbotDisplayMode) => void;\n};\n\nconst StyledDropdown = styled(Dropdown)({\n '& ul, & li': {\n padding: 0,\n margin: 0,\n },\n});\n\nconst StyledOptionsDropdown = styled(ChatbotHeaderOptionsDropdown)({\n '& ul, & li': {\n padding: 0,\n margin: 0,\n },\n});\n\nconst SelectorToggle = styled(MenuToggle, {\n shouldForwardProp: prop => prop !== 'dimmed',\n})<{ dimmed?: boolean }>(({ theme, dimmed }) => ({\n ...(dimmed && {\n backgroundColor: theme.palette.action.disabled,\n }),\n}));\n\nconst StyledDropdownGroup = styled(DropdownGroup)({\n fontWeight: 'bold',\n});\n\nexport const LightspeedChatBoxHeader = ({\n selectedModel,\n displayMode,\n handleSelectedModel,\n models,\n isPinningChatsEnabled,\n onPinnedChatsToggle,\n isSavedPromptsEnabled,\n onSavedPromptsToggle,\n onMcpSettingsClick,\n isModelSelectorDisabled = false,\n hideModelSelector = false,\n showChatTabOptions = true,\n showMcpSettings = false,\n setDisplayMode,\n}: LightspeedChatBoxHeaderProps) => {\n const [isOptionsMenuOpen, setIsOptionsMenuOpen] = useState(false);\n const { t } = useTranslation();\n\n const maxLabelLength = Math.max(\n ...models.map(m => m.label.length),\n selectedModel.length,\n 1,\n );\n const toggleMinWidth = `${maxLabelLength + 4}ch`;\n\n const toggle = (toggleRef: Ref<MenuToggleElement>) => (\n <SelectorToggle\n dimmed={isModelSelectorDisabled}\n variant=\"secondary\"\n aria-label={t('aria.chatbotSelector')}\n ref={toggleRef}\n isExpanded={isOptionsMenuOpen}\n isDisabled={isModelSelectorDisabled}\n onClick={() => setIsOptionsMenuOpen(!isOptionsMenuOpen)}\n style={{ minWidth: toggleMinWidth }}\n >\n {selectedModel}\n </SelectorToggle>\n );\n\n const handlePinningChatsToggle = (state: boolean) => {\n onPinnedChatsToggle(state);\n };\n\n const handleDockedToWindow = () => {\n setDisplayMode(ChatbotDisplayMode.docked);\n };\n\n const handleFullscreen = () => {\n setDisplayMode(ChatbotDisplayMode.embedded);\n };\n\n const handleOverlay = () => {\n setDisplayMode(ChatbotDisplayMode.default);\n };\n\n const isOverlayMode = displayMode === ChatbotDisplayMode.default;\n const scrollThreshold = isOverlayMode ? 8 : 10;\n const isModelDropdownScrollable = models.length > scrollThreshold;\n\n return (\n <ChatbotHeaderActions>\n {!hideModelSelector && (\n <StyledDropdown\n isOpen={isOptionsMenuOpen}\n onSelect={(_e, value) => {\n handleSelectedModel(value as string);\n setIsOptionsMenuOpen(false);\n }}\n onOpenChange={isOpen => setIsOptionsMenuOpen(isOpen)}\n popperProps={{ position: 'right' }}\n shouldFocusToggleOnSelect\n shouldFocusFirstItemOnOpen={false}\n toggle={toggle}\n isScrollable={isModelDropdownScrollable}\n maxMenuHeight={isModelDropdownScrollable ? '240px' : undefined}\n >\n <DropdownList>\n {models.map(model => (\n <StyledDropdownGroup key={model.label}>\n <DropdownItem\n value={model.value}\n key={model.value}\n isSelected={selectedModel === model.value}\n >\n {model.label}\n </DropdownItem>\n </StyledDropdownGroup>\n ))}\n </DropdownList>\n </StyledDropdown>\n )}\n <StyledOptionsDropdown\n isCompact\n shouldFocusFirstItemOnOpen={false}\n popperProps={{\n position: 'right',\n preventOverflow: true,\n appendTo: () => document.body,\n }}\n toggleProps={{\n 'aria-label': t('aria.options.label'),\n className: 'pf-chatbot__button--toggle-options pf-m-compact',\n icon: (\n <Icon size=\"lg\" isInline>\n <RhUiEllipsisVerticalFillIcon />\n </Icon>\n ),\n }}\n tooltipProps={{\n trigger: 'manual',\n content: '',\n }}\n >\n <DropdownGroup>\n <DropdownList>\n <DropdownItem key=\"displayModeLabel\" isDisabled>\n {t('settings.displayMode.label')}\n </DropdownItem>\n <DropdownItem\n value={ChatbotDisplayMode.default}\n key=\"switchDisplayOverlay\"\n icon={<OutlinedWindowRestoreIcon />}\n onClick={handleOverlay}\n isSelected={displayMode === ChatbotDisplayMode.default}\n >\n {t('settings.displayMode.overlay')}\n </DropdownItem>\n <DropdownItem\n value={ChatbotDisplayMode.docked}\n key=\"switchDisplayDock\"\n icon={<OpenDrawerRightIcon />}\n onClick={handleDockedToWindow}\n isSelected={displayMode === ChatbotDisplayMode.docked}\n >\n {t('settings.displayMode.docked')}\n </DropdownItem>\n <DropdownItem\n value={ChatbotDisplayMode.embedded}\n key=\"switchDisplayFullscreen\"\n icon={<ExpandIcon />}\n onClick={handleFullscreen}\n isSelected={displayMode === ChatbotDisplayMode.embedded}\n >\n {t('settings.displayMode.fullscreen')}\n </DropdownItem>\n </DropdownList>\n </DropdownGroup>\n {showChatTabOptions && (\n <>\n <Divider />\n <DropdownGroup>\n <DropdownList>\n {isPinningChatsEnabled ? (\n <DropdownItem\n value=\"disablePinningChats\"\n key=\"disablePinningChat\"\n icon={<ToggleOnOutlinedIcon sx={{ marginTop: '8px' }} />}\n description={t('settings.pinned.enabled.description')}\n onClick={() => handlePinningChatsToggle(false)}\n >\n {t('settings.pinned.disable')}\n </DropdownItem>\n ) : (\n <DropdownItem\n value=\"enablePinningChats\"\n key=\"enablePinningChats\"\n icon={<ToggleOffOutlinedIcon sx={{ marginTop: '8px' }} />}\n description={t('settings.pinned.disabled.description')}\n onClick={() => handlePinningChatsToggle(true)}\n >\n {t('settings.pinned.enable')}\n </DropdownItem>\n )}\n {isSavedPromptsEnabled ? (\n <DropdownItem\n value=\"disableSavedPrompts\"\n key=\"disableSavedPrompts\"\n icon={<ToggleOnOutlinedIcon sx={{ marginTop: '8px' }} />}\n description={t('settings.savedPrompts.enabled.description')}\n onClick={() => onSavedPromptsToggle(false)}\n >\n {t('settings.savedPrompts.disable')}\n </DropdownItem>\n ) : (\n <DropdownItem\n value=\"enableSavedPrompts\"\n key=\"enableSavedPrompts\"\n icon={<ToggleOffOutlinedIcon sx={{ marginTop: '8px' }} />}\n description={t(\n 'settings.savedPrompts.disabled.description',\n )}\n onClick={() => onSavedPromptsToggle(true)}\n >\n {t('settings.savedPrompts.enable')}\n </DropdownItem>\n )}\n <DropdownItem\n value=\"mcpSettings\"\n key=\"mcpSettings\"\n icon={<McpSettingsIcon />}\n onClick={onMcpSettingsClick}\n >\n {t(\n showMcpSettings\n ? 'settings.mcp.label'\n : 'settings.prompt.label',\n )}\n <Label color=\"purple\" isCompact style={{ marginLeft: 8 }}>\n {t('settings.mcp.badge')}\n </Label>\n </DropdownItem>\n </DropdownList>\n </DropdownGroup>\n </>\n )}\n </StyledOptionsDropdown>\n </ChatbotHeaderActions>\n );\n};\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"LightspeedChatBoxHeader.esm.js","sources":["../../src/components/LightspeedChatBoxHeader.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 { Ref, useState } from 'react';\n\nimport ToggleOffOutlinedIcon from '@mui/icons-material/ToggleOffOutlined';\nimport ToggleOnOutlinedIcon from '@mui/icons-material/ToggleOnOutlined';\nimport Divider from '@mui/material/Divider';\nimport { styled } from '@mui/material/styles';\nimport {\n ChatbotDisplayMode,\n ChatbotHeaderActions,\n ChatbotHeaderOptionsDropdown,\n} from '@patternfly/chatbot';\nimport {\n Dropdown,\n DropdownGroup,\n DropdownItem,\n DropdownList,\n Icon,\n Label,\n MenuToggle,\n MenuToggleElement,\n} from '@patternfly/react-core';\nimport {\n ExpandIcon,\n OpenDrawerRightIcon,\n OutlinedWindowRestoreIcon,\n RhUiEllipsisVerticalFillIcon,\n} from '@patternfly/react-icons';\n\nimport { useTranslation } from '../hooks/useTranslation';\nimport { McpSettingsIcon } from './McpSettingsIcon';\n\ntype LightspeedChatBoxHeaderProps = {\n displayMode: ChatbotDisplayMode;\n selectedModel: string;\n handleSelectedModel: (item: string) => void;\n models: { label: string; value: string; provider: string }[];\n isPinningChatsEnabled: boolean;\n onPinnedChatsToggle: (state: boolean) => void;\n isSavedPromptsEnabled: boolean;\n onSavedPromptsToggle: (state: boolean) => void;\n screenContextAdminEnabled?: boolean;\n isScreenContextSharingEnabled?: boolean;\n onScreenContextSharingToggle?: (state: boolean) => void;\n onMcpSettingsClick: () => void;\n isModelSelectorDisabled?: boolean;\n hideModelSelector?: boolean;\n /** When false, omits pinned-chats and MCP entries (Chat tab only). */\n showChatTabOptions?: boolean;\n /** When false, shows prompt-only settings label and opens saved-prompts tab. */\n showMcpSettings?: boolean;\n setDisplayMode: (mode: ChatbotDisplayMode) => void;\n};\n\nconst StyledDropdown = styled(Dropdown)({\n '& ul, & li': {\n padding: 0,\n margin: 0,\n },\n});\n\nconst StyledOptionsDropdown = styled(ChatbotHeaderOptionsDropdown)({\n '& ul, & li': {\n padding: 0,\n margin: 0,\n },\n});\n\nconst SelectorToggle = styled(MenuToggle, {\n shouldForwardProp: prop => prop !== 'dimmed',\n})<{ dimmed?: boolean }>(({ theme, dimmed }) => ({\n ...(dimmed && {\n backgroundColor: theme.palette.action.disabled,\n }),\n}));\n\nconst StyledDropdownGroup = styled(DropdownGroup)({\n fontWeight: 'bold',\n});\n\nexport const LightspeedChatBoxHeader = ({\n selectedModel,\n displayMode,\n handleSelectedModel,\n models,\n isPinningChatsEnabled,\n onPinnedChatsToggle,\n isSavedPromptsEnabled,\n onSavedPromptsToggle,\n screenContextAdminEnabled = false,\n isScreenContextSharingEnabled = false,\n onScreenContextSharingToggle,\n onMcpSettingsClick,\n isModelSelectorDisabled = false,\n hideModelSelector = false,\n showChatTabOptions = true,\n showMcpSettings = false,\n setDisplayMode,\n}: LightspeedChatBoxHeaderProps) => {\n const [isOptionsMenuOpen, setIsOptionsMenuOpen] = useState(false);\n const { t } = useTranslation();\n\n const maxLabelLength = Math.max(\n ...models.map(m => m.label.length),\n selectedModel.length,\n 1,\n );\n const toggleMinWidth = `${maxLabelLength + 4}ch`;\n\n const toggle = (toggleRef: Ref<MenuToggleElement>) => (\n <SelectorToggle\n dimmed={isModelSelectorDisabled}\n variant=\"secondary\"\n aria-label={t('aria.chatbotSelector')}\n ref={toggleRef}\n isExpanded={isOptionsMenuOpen}\n isDisabled={isModelSelectorDisabled}\n onClick={() => setIsOptionsMenuOpen(!isOptionsMenuOpen)}\n style={{ minWidth: toggleMinWidth }}\n >\n {selectedModel}\n </SelectorToggle>\n );\n\n const handlePinningChatsToggle = (state: boolean) => {\n onPinnedChatsToggle(state);\n };\n\n const handleDockedToWindow = () => {\n setDisplayMode(ChatbotDisplayMode.docked);\n };\n\n const handleFullscreen = () => {\n setDisplayMode(ChatbotDisplayMode.embedded);\n };\n\n const handleOverlay = () => {\n setDisplayMode(ChatbotDisplayMode.default);\n };\n\n const isOverlayMode = displayMode === ChatbotDisplayMode.default;\n const scrollThreshold = isOverlayMode ? 8 : 10;\n const isModelDropdownScrollable = models.length > scrollThreshold;\n\n return (\n <ChatbotHeaderActions>\n {!hideModelSelector && (\n <StyledDropdown\n isOpen={isOptionsMenuOpen}\n onSelect={(_e, value) => {\n handleSelectedModel(value as string);\n setIsOptionsMenuOpen(false);\n }}\n onOpenChange={isOpen => setIsOptionsMenuOpen(isOpen)}\n popperProps={{ position: 'right' }}\n shouldFocusToggleOnSelect\n shouldFocusFirstItemOnOpen={false}\n toggle={toggle}\n isScrollable={isModelDropdownScrollable}\n maxMenuHeight={isModelDropdownScrollable ? '240px' : undefined}\n >\n <DropdownList>\n {models.map(model => (\n <StyledDropdownGroup key={model.label}>\n <DropdownItem\n value={model.value}\n key={model.value}\n isSelected={selectedModel === model.value}\n >\n {model.label}\n </DropdownItem>\n </StyledDropdownGroup>\n ))}\n </DropdownList>\n </StyledDropdown>\n )}\n <StyledOptionsDropdown\n isCompact\n shouldFocusFirstItemOnOpen={false}\n popperProps={{\n position: 'right',\n preventOverflow: true,\n appendTo: () => document.body,\n }}\n toggleProps={{\n 'aria-label': t('aria.options.label'),\n className: 'pf-chatbot__button--toggle-options pf-m-compact',\n icon: (\n <Icon size=\"lg\" isInline>\n <RhUiEllipsisVerticalFillIcon />\n </Icon>\n ),\n }}\n tooltipProps={{\n trigger: 'manual',\n content: '',\n }}\n >\n <DropdownGroup>\n <DropdownList>\n <DropdownItem key=\"displayModeLabel\" isDisabled>\n {t('settings.displayMode.label')}\n </DropdownItem>\n <DropdownItem\n value={ChatbotDisplayMode.default}\n key=\"switchDisplayOverlay\"\n icon={<OutlinedWindowRestoreIcon />}\n onClick={handleOverlay}\n isSelected={displayMode === ChatbotDisplayMode.default}\n >\n {t('settings.displayMode.overlay')}\n </DropdownItem>\n <DropdownItem\n value={ChatbotDisplayMode.docked}\n key=\"switchDisplayDock\"\n icon={<OpenDrawerRightIcon />}\n onClick={handleDockedToWindow}\n isSelected={displayMode === ChatbotDisplayMode.docked}\n >\n {t('settings.displayMode.docked')}\n </DropdownItem>\n <DropdownItem\n value={ChatbotDisplayMode.embedded}\n key=\"switchDisplayFullscreen\"\n icon={<ExpandIcon />}\n onClick={handleFullscreen}\n isSelected={displayMode === ChatbotDisplayMode.embedded}\n >\n {t('settings.displayMode.fullscreen')}\n </DropdownItem>\n </DropdownList>\n </DropdownGroup>\n {showChatTabOptions && (\n <>\n <Divider />\n <DropdownGroup>\n <DropdownList>\n {isPinningChatsEnabled ? (\n <DropdownItem\n value=\"disablePinningChats\"\n key=\"disablePinningChat\"\n icon={<ToggleOnOutlinedIcon sx={{ marginTop: '8px' }} />}\n description={t('settings.pinned.enabled.description')}\n onClick={() => handlePinningChatsToggle(false)}\n >\n {t('settings.pinned.disable')}\n </DropdownItem>\n ) : (\n <DropdownItem\n value=\"enablePinningChats\"\n key=\"enablePinningChats\"\n icon={<ToggleOffOutlinedIcon sx={{ marginTop: '8px' }} />}\n description={t('settings.pinned.disabled.description')}\n onClick={() => handlePinningChatsToggle(true)}\n >\n {t('settings.pinned.enable')}\n </DropdownItem>\n )}\n {isSavedPromptsEnabled ? (\n <DropdownItem\n value=\"disableSavedPrompts\"\n key=\"disableSavedPrompts\"\n icon={<ToggleOnOutlinedIcon sx={{ marginTop: '8px' }} />}\n description={t('settings.savedPrompts.enabled.description')}\n onClick={() => onSavedPromptsToggle(false)}\n >\n {t('settings.savedPrompts.disable')}\n </DropdownItem>\n ) : (\n <DropdownItem\n value=\"enableSavedPrompts\"\n key=\"enableSavedPrompts\"\n icon={<ToggleOffOutlinedIcon sx={{ marginTop: '8px' }} />}\n description={t(\n 'settings.savedPrompts.disabled.description',\n )}\n onClick={() => onSavedPromptsToggle(true)}\n >\n {t('settings.savedPrompts.enable')}\n </DropdownItem>\n )}\n {screenContextAdminEnabled &&\n (isScreenContextSharingEnabled ? (\n <DropdownItem\n value=\"disableScreenContext\"\n key=\"disableScreenContext\"\n icon={<ToggleOnOutlinedIcon sx={{ marginTop: '8px' }} />}\n description={t(\n 'settings.screenContext.enabled.description',\n )}\n onClick={() => onScreenContextSharingToggle?.(false)}\n >\n {t('settings.screenContext.disable')}\n </DropdownItem>\n ) : (\n <DropdownItem\n value=\"enableScreenContext\"\n key=\"enableScreenContext\"\n icon={<ToggleOffOutlinedIcon sx={{ marginTop: '8px' }} />}\n description={t(\n 'settings.screenContext.disabled.description',\n )}\n onClick={() => onScreenContextSharingToggle?.(true)}\n >\n {t('settings.screenContext.enable')}\n </DropdownItem>\n ))}\n <DropdownItem\n value=\"mcpSettings\"\n key=\"mcpSettings\"\n icon={<McpSettingsIcon />}\n onClick={onMcpSettingsClick}\n >\n {t(\n showMcpSettings\n ? 'settings.mcp.label'\n : 'settings.prompt.label',\n )}\n <Label color=\"purple\" isCompact style={{ marginLeft: 8 }}>\n {t('settings.mcp.badge')}\n </Label>\n </DropdownItem>\n </DropdownList>\n </DropdownGroup>\n </>\n )}\n </StyledOptionsDropdown>\n </ChatbotHeaderActions>\n );\n};\n"],"names":[],"mappings":"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"}
|
|
@@ -43,7 +43,8 @@ const LightspeedChatContainerInner = () => {
|
|
|
43
43
|
() => models ? models.filter((model) => model.model_type === "llm").map((m) => ({
|
|
44
44
|
label: m.provider_resource_id,
|
|
45
45
|
value: m.provider_resource_id,
|
|
46
|
-
provider: m.provider_id
|
|
46
|
+
provider: m.provider_id,
|
|
47
|
+
supportsVision: m.supportsVision
|
|
47
48
|
})) : [],
|
|
48
49
|
[models]
|
|
49
50
|
);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LightspeedChatContainer.esm.js","sources":["../../src/components/LightspeedChatContainer.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 '@patternfly/react-core/dist/styles/base-no-reset.css';\nimport '@patternfly/chatbot/dist/css/main.css';\n\nimport { useEffect, useLayoutEffect, useMemo, useState } from 'react';\nimport { useAsync } from 'react-use';\n\nimport { identityApiRef, useApi } from '@backstage/core-plugin-api';\n\nimport { useTheme } from '@mui/material/styles';\nimport { QueryClientProvider } from '@tanstack/react-query';\n\nimport { useAllModels } from '../hooks/useAllModels';\nimport { useIaChatPermission } from '../hooks/useIaChatPermission';\nimport { useIaNotebooksPermission } from '../hooks/useIaNotebooksPermission';\nimport { useTopicRestrictionStatus } from '../hooks/useQuestionValidation';\nimport queryClient from '../utils/queryClient';\nimport FileAttachmentContextProvider from './AttachmentContext';\nimport { LightspeedChat } from './LightSpeedChat';\nimport {\n LcoreNotConfiguredEmptyState,\n LightspeedChatModelsLoading,\n ModelsLoadErrorEmptyState,\n} from './LightspeedChatModelsState';\n\nconst THEME_DARK = 'dark';\nconst THEME_DARK_CLASS = 'pf-v6-theme-dark';\nconst LAST_SELECTED_MODEL_KEY = 'lastSelectedModel';\n\n/**\n * Inner component that contains all the Lightspeed chat rendering logic\n */\nconst LightspeedChatContainerInner = () => {\n const {\n palette: { mode },\n } = useTheme();\n\n const identityApi = useApi(identityApiRef);\n\n const { allowed: hasChatAccess, loading: chatPermissionLoading } =\n useIaChatPermission();\n\n const { allowed: hasNotebooksAccess, loading: notebooksPermissionLoading } =\n useIaNotebooksPermission();\n\n const permissionsLoading =\n chatPermissionLoading || notebooksPermissionLoading;\n const hasPluginAccess = hasChatAccess || hasNotebooksAccess;\n\n const {\n data: models,\n isLoading: modelsLoading,\n isError: modelsError,\n refetch: refetchModels,\n } = useAllModels(hasChatAccess);\n\n const { value: profile, loading: profileLoading } = useAsync(\n async () => await identityApi.getProfileInfo(),\n );\n\n const [selectedModel, setSelectedModel] = useState('');\n const [selectedProvider, setSelectedProvider] = useState('');\n\n const { data: topicRestrictionEnabled } =\n useTopicRestrictionStatus(hasChatAccess);\n\n const modelsItems = useMemo(\n () =>\n models\n ? models\n .filter(model => model.model_type === 'llm')\n .map(m => ({\n label: m.provider_resource_id,\n value: m.provider_resource_id,\n provider: m.provider_id,\n }))\n : [],\n [models],\n );\n\n useLayoutEffect(() => {\n const htmlTagElement = document.documentElement;\n if (mode === THEME_DARK) {\n htmlTagElement.classList.add(THEME_DARK_CLASS);\n } else {\n htmlTagElement.classList.remove(THEME_DARK_CLASS);\n }\n }, [mode]);\n\n // Load last selected model from localStorage\n useEffect(() => {\n if (!hasChatAccess || modelsItems.length === 0) {\n return;\n }\n\n try {\n const storedData = localStorage.getItem(LAST_SELECTED_MODEL_KEY);\n const parsedData = storedData ? JSON.parse(storedData) : null;\n\n const storedModel = parsedData?.model\n ? modelsItems.find(m => m.value === parsedData.model)\n : null;\n\n if (storedModel) {\n setSelectedModel(storedModel.value);\n setSelectedProvider(storedModel.provider);\n } else {\n setSelectedModel(modelsItems[0].value);\n setSelectedProvider(modelsItems[0].provider);\n }\n } catch (error) {\n // eslint-disable-next-line no-console\n console.error(\n 'Error loading last selected model from localStorage:',\n error,\n );\n setSelectedModel(modelsItems[0].value);\n setSelectedProvider(modelsItems[0].provider);\n }\n }, [hasChatAccess, modelsItems]);\n\n // Save selected model to localStorage\n useEffect(() => {\n if (selectedModel && selectedProvider) {\n try {\n localStorage.setItem(\n LAST_SELECTED_MODEL_KEY,\n JSON.stringify({\n model: selectedModel,\n provider: selectedProvider,\n }),\n );\n } catch (error) {\n // eslint-disable-next-line no-console\n console.error(\n 'Error saving last selected model to localStorage:',\n error,\n );\n }\n }\n }, [selectedModel, selectedProvider]);\n\n if (permissionsLoading) {\n // Never return null inside the overlay modal: PatternFly's focus-trap requires at least\n // one tabbable node (e.g. after removing the modal close button). Locale switches can\n // briefly re-enter this loading state.\n return <LightspeedChatModelsLoading />;\n }\n\n if (!hasPluginAccess) {\n return null;\n }\n\n if (hasChatAccess && modelsLoading) {\n return <LightspeedChatModelsLoading />;\n }\n\n // TanStack Query can keep the last successful `data` while `isError` is true after a\n // failed refetch. Prefer showing chat when we still have LLM rows; only use the full-page\n // error state when there is nothing usable to render.\n if (hasChatAccess && modelsError && modelsItems.length === 0) {\n return <ModelsLoadErrorEmptyState onRetry={() => refetchModels()} />;\n }\n\n if (hasChatAccess && modelsItems.length === 0) {\n return <LcoreNotConfiguredEmptyState />;\n }\n\n const resolvedSelectedModel = selectedModel || modelsItems[0]?.value || '';\n const resolvedSelectedProvider =\n selectedProvider || modelsItems[0]?.provider || '';\n\n return (\n <FileAttachmentContextProvider>\n <LightspeedChat\n selectedModel={resolvedSelectedModel}\n selectedProvider={resolvedSelectedProvider}\n topicRestrictionEnabled={topicRestrictionEnabled ?? false}\n handleSelectedModel={item => {\n setSelectedModel(item);\n setSelectedProvider(\n modelsItems.find((m: any) => m.value === item)?.provider || '',\n );\n }}\n models={modelsItems}\n userName={profile?.displayName}\n avatar={profile?.picture}\n profileLoading={profileLoading}\n />\n </FileAttachmentContextProvider>\n );\n};\n\n/**\n * @public\n */\nexport const LightspeedChatContainer = () => {\n return (\n <QueryClientProvider client={queryClient}>\n <LightspeedChatContainerInner />\n </QueryClientProvider>\n );\n};\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"LightspeedChatContainer.esm.js","sources":["../../src/components/LightspeedChatContainer.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 '@patternfly/react-core/dist/styles/base-no-reset.css';\nimport '@patternfly/chatbot/dist/css/main.css';\n\nimport { useEffect, useLayoutEffect, useMemo, useState } from 'react';\nimport { useAsync } from 'react-use';\n\nimport { identityApiRef, useApi } from '@backstage/core-plugin-api';\n\nimport { useTheme } from '@mui/material/styles';\nimport { QueryClientProvider } from '@tanstack/react-query';\n\nimport { useAllModels } from '../hooks/useAllModels';\nimport { useIaChatPermission } from '../hooks/useIaChatPermission';\nimport { useIaNotebooksPermission } from '../hooks/useIaNotebooksPermission';\nimport { useTopicRestrictionStatus } from '../hooks/useQuestionValidation';\nimport queryClient from '../utils/queryClient';\nimport FileAttachmentContextProvider from './AttachmentContext';\nimport { LightspeedChat } from './LightSpeedChat';\nimport {\n LcoreNotConfiguredEmptyState,\n LightspeedChatModelsLoading,\n ModelsLoadErrorEmptyState,\n} from './LightspeedChatModelsState';\n\nconst THEME_DARK = 'dark';\nconst THEME_DARK_CLASS = 'pf-v6-theme-dark';\nconst LAST_SELECTED_MODEL_KEY = 'lastSelectedModel';\n\n/**\n * Inner component that contains all the Lightspeed chat rendering logic\n */\nconst LightspeedChatContainerInner = () => {\n const {\n palette: { mode },\n } = useTheme();\n\n const identityApi = useApi(identityApiRef);\n\n const { allowed: hasChatAccess, loading: chatPermissionLoading } =\n useIaChatPermission();\n\n const { allowed: hasNotebooksAccess, loading: notebooksPermissionLoading } =\n useIaNotebooksPermission();\n\n const permissionsLoading =\n chatPermissionLoading || notebooksPermissionLoading;\n const hasPluginAccess = hasChatAccess || hasNotebooksAccess;\n\n const {\n data: models,\n isLoading: modelsLoading,\n isError: modelsError,\n refetch: refetchModels,\n } = useAllModels(hasChatAccess);\n\n const { value: profile, loading: profileLoading } = useAsync(\n async () => await identityApi.getProfileInfo(),\n );\n\n const [selectedModel, setSelectedModel] = useState('');\n const [selectedProvider, setSelectedProvider] = useState('');\n\n const { data: topicRestrictionEnabled } =\n useTopicRestrictionStatus(hasChatAccess);\n\n const modelsItems = useMemo(\n () =>\n models\n ? models\n .filter(model => model.model_type === 'llm')\n .map(m => ({\n label: m.provider_resource_id,\n value: m.provider_resource_id,\n provider: m.provider_id,\n supportsVision: m.supportsVision,\n }))\n : [],\n [models],\n );\n\n useLayoutEffect(() => {\n const htmlTagElement = document.documentElement;\n if (mode === THEME_DARK) {\n htmlTagElement.classList.add(THEME_DARK_CLASS);\n } else {\n htmlTagElement.classList.remove(THEME_DARK_CLASS);\n }\n }, [mode]);\n\n // Load last selected model from localStorage\n useEffect(() => {\n if (!hasChatAccess || modelsItems.length === 0) {\n return;\n }\n\n try {\n const storedData = localStorage.getItem(LAST_SELECTED_MODEL_KEY);\n const parsedData = storedData ? JSON.parse(storedData) : null;\n\n const storedModel = parsedData?.model\n ? modelsItems.find(m => m.value === parsedData.model)\n : null;\n\n if (storedModel) {\n setSelectedModel(storedModel.value);\n setSelectedProvider(storedModel.provider);\n } else {\n setSelectedModel(modelsItems[0].value);\n setSelectedProvider(modelsItems[0].provider);\n }\n } catch (error) {\n // eslint-disable-next-line no-console\n console.error(\n 'Error loading last selected model from localStorage:',\n error,\n );\n setSelectedModel(modelsItems[0].value);\n setSelectedProvider(modelsItems[0].provider);\n }\n }, [hasChatAccess, modelsItems]);\n\n // Save selected model to localStorage\n useEffect(() => {\n if (selectedModel && selectedProvider) {\n try {\n localStorage.setItem(\n LAST_SELECTED_MODEL_KEY,\n JSON.stringify({\n model: selectedModel,\n provider: selectedProvider,\n }),\n );\n } catch (error) {\n // eslint-disable-next-line no-console\n console.error(\n 'Error saving last selected model to localStorage:',\n error,\n );\n }\n }\n }, [selectedModel, selectedProvider]);\n\n if (permissionsLoading) {\n // Never return null inside the overlay modal: PatternFly's focus-trap requires at least\n // one tabbable node (e.g. after removing the modal close button). Locale switches can\n // briefly re-enter this loading state.\n return <LightspeedChatModelsLoading />;\n }\n\n if (!hasPluginAccess) {\n return null;\n }\n\n if (hasChatAccess && modelsLoading) {\n return <LightspeedChatModelsLoading />;\n }\n\n // TanStack Query can keep the last successful `data` while `isError` is true after a\n // failed refetch. Prefer showing chat when we still have LLM rows; only use the full-page\n // error state when there is nothing usable to render.\n if (hasChatAccess && modelsError && modelsItems.length === 0) {\n return <ModelsLoadErrorEmptyState onRetry={() => refetchModels()} />;\n }\n\n if (hasChatAccess && modelsItems.length === 0) {\n return <LcoreNotConfiguredEmptyState />;\n }\n\n const resolvedSelectedModel = selectedModel || modelsItems[0]?.value || '';\n const resolvedSelectedProvider =\n selectedProvider || modelsItems[0]?.provider || '';\n\n return (\n <FileAttachmentContextProvider>\n <LightspeedChat\n selectedModel={resolvedSelectedModel}\n selectedProvider={resolvedSelectedProvider}\n topicRestrictionEnabled={topicRestrictionEnabled ?? false}\n handleSelectedModel={item => {\n setSelectedModel(item);\n setSelectedProvider(\n modelsItems.find((m: any) => m.value === item)?.provider || '',\n );\n }}\n models={modelsItems}\n userName={profile?.displayName}\n avatar={profile?.picture}\n profileLoading={profileLoading}\n />\n </FileAttachmentContextProvider>\n );\n};\n\n/**\n * @public\n */\nexport const LightspeedChatContainer = () => {\n return (\n <QueryClientProvider client={queryClient}>\n <LightspeedChatContainerInner />\n </QueryClientProvider>\n );\n};\n"],"names":[],"mappings":"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"}
|
|
@@ -32,6 +32,7 @@ const LightspeedDrawerProvider = ({ children }) => {
|
|
|
32
32
|
onEscapePress: () => closeChatbot(),
|
|
33
33
|
ouiaId: "LightspeedChatbotModal",
|
|
34
34
|
"aria-labelledby": "lightspeed-chatpopup-modal",
|
|
35
|
+
"data-screen-capture-exclude": true,
|
|
35
36
|
children: /* @__PURE__ */ jsx(LightspeedChatContainer, {})
|
|
36
37
|
}
|
|
37
38
|
)
|
|
@@ -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 { styled } from '@mui/material/styles';\nimport { ChatbotModal } from '@patternfly/chatbot';\n\nimport {\n DOCKED_CONTENT_OFFSET,\n LIGHTSPEED_OVERLAY_BOTTOM,\n LIGHTSPEED_OVERLAY_CHATBOT_MODAL_CLASS,\n LIGHTSPEED_OVERLAY_MAX_WIDTH,\n LIGHTSPEED_OVERLAY_RIGHT,\n} from '../const';\nimport { useLightspeedProviderState } from '../hooks/useLightspeedProviderState';\nimport { LightspeedChatContainer } from './LightspeedChatContainer';\nimport { LightspeedDrawerContext } from './LightspeedDrawerContext';\nimport { NotebookStreamProvider } from './notebooks/NotebookStreamProvider';\n\nconst StyledChatbotModal = styled(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: `${LIGHTSPEED_OVERLAY_BOTTOM} !important`,\n right: `${LIGHTSPEED_OVERLAY_RIGHT} !important`,\n maxWidth: `${LIGHTSPEED_OVERLAY_MAX_WIDTH} !important`,\n overflow: 'hidden',\n transition:\n 'margin-right 0.3s ease, bottom 0.3s ease, right 0.3s ease, inset-block-end 0.3s ease, inset-inline-end 0.3s ease',\n 'body.docked-drawer-open &': {\n marginRight: DOCKED_CONTENT_OFFSET,\n },\n}));\n\n/**\n * @public\n */\nexport const LightspeedDrawerProvider = ({ children }: PropsWithChildren) => {\n const { contextValue, shouldRenderOverlayModal, closeChatbot } =\n useLightspeedProviderState();\n\n return (\n <LightspeedDrawerContext.Provider value={contextValue}>\n <NotebookStreamProvider>\n {children}\n {shouldRenderOverlayModal && (\n <StyledChatbotModal\n isOpen\n className={LIGHTSPEED_OVERLAY_CHATBOT_MODAL_CLASS}\n displayMode={contextValue.displayMode}\n disableFocusTrap\n onEscapePress={() => closeChatbot()}\n ouiaId=\"LightspeedChatbotModal\"\n aria-labelledby=\"lightspeed-chatpopup-modal\"\n >\n <LightspeedChatContainer />\n </StyledChatbotModal>\n )}\n </NotebookStreamProvider>\n </LightspeedDrawerContext.Provider>\n );\n};\n"],"names":[],"mappings":";;;;;;;;;AAiCA,MAAM,kBAAA,GAAqB,MAAA,CAAO,YAAY,CAAA,CAAE,OAAO;AAAA,EACrD,SAAA,EACE,4HAAA;AAAA,EACF,MAAA,EAAQ,GAAG,yBAAyB,CAAA,WAAA,CAAA;AAAA,EACpC,KAAA,EAAO,GAAG,wBAAwB,CAAA,WAAA,CAAA;AAAA,EAClC,QAAA,EAAU,GAAG,4BAA4B,CAAA,WAAA,CAAA;AAAA,EACzC,QAAA,EAAU,QAAA;AAAA,EACV,UAAA,EACE,kHAAA;AAAA,EACF,2BAAA,EAA6B;AAAA,IAC3B,WAAA,EAAa;AAAA;AAEjB,CAAA,CAAE,CAAA;AAKK,MAAM,wBAAA,GAA2B,CAAC,EAAE,QAAA,EAAS,KAAyB;AAC3E,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,kBAAA;AAAA,MAAA;AAAA,QACC,MAAA,EAAM,IAAA;AAAA,QACN,SAAA,EAAW,sCAAA;AAAA,QACX,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,
|
|
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 { styled } from '@mui/material/styles';\nimport { ChatbotModal } from '@patternfly/chatbot';\n\nimport {\n DOCKED_CONTENT_OFFSET,\n LIGHTSPEED_OVERLAY_BOTTOM,\n LIGHTSPEED_OVERLAY_CHATBOT_MODAL_CLASS,\n LIGHTSPEED_OVERLAY_MAX_WIDTH,\n LIGHTSPEED_OVERLAY_RIGHT,\n} from '../const';\nimport { useLightspeedProviderState } from '../hooks/useLightspeedProviderState';\nimport { LightspeedChatContainer } from './LightspeedChatContainer';\nimport { LightspeedDrawerContext } from './LightspeedDrawerContext';\nimport { NotebookStreamProvider } from './notebooks/NotebookStreamProvider';\n\nconst StyledChatbotModal = styled(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: `${LIGHTSPEED_OVERLAY_BOTTOM} !important`,\n right: `${LIGHTSPEED_OVERLAY_RIGHT} !important`,\n maxWidth: `${LIGHTSPEED_OVERLAY_MAX_WIDTH} !important`,\n overflow: 'hidden',\n transition:\n 'margin-right 0.3s ease, bottom 0.3s ease, right 0.3s ease, inset-block-end 0.3s ease, inset-inline-end 0.3s ease',\n 'body.docked-drawer-open &': {\n marginRight: DOCKED_CONTENT_OFFSET,\n },\n}));\n\n/**\n * @public\n */\nexport const LightspeedDrawerProvider = ({ children }: PropsWithChildren) => {\n const { contextValue, shouldRenderOverlayModal, closeChatbot } =\n useLightspeedProviderState();\n\n return (\n <LightspeedDrawerContext.Provider value={contextValue}>\n <NotebookStreamProvider>\n {children}\n {shouldRenderOverlayModal && (\n <StyledChatbotModal\n isOpen\n className={LIGHTSPEED_OVERLAY_CHATBOT_MODAL_CLASS}\n displayMode={contextValue.displayMode}\n disableFocusTrap\n onEscapePress={() => closeChatbot()}\n ouiaId=\"LightspeedChatbotModal\"\n aria-labelledby=\"lightspeed-chatpopup-modal\"\n data-screen-capture-exclude\n >\n <LightspeedChatContainer />\n </StyledChatbotModal>\n )}\n </NotebookStreamProvider>\n </LightspeedDrawerContext.Provider>\n );\n};\n"],"names":[],"mappings":";;;;;;;;;AAiCA,MAAM,kBAAA,GAAqB,MAAA,CAAO,YAAY,CAAA,CAAE,OAAO;AAAA,EACrD,SAAA,EACE,4HAAA;AAAA,EACF,MAAA,EAAQ,GAAG,yBAAyB,CAAA,WAAA,CAAA;AAAA,EACpC,KAAA,EAAO,GAAG,wBAAwB,CAAA,WAAA,CAAA;AAAA,EAClC,QAAA,EAAU,GAAG,4BAA4B,CAAA,WAAA,CAAA;AAAA,EACzC,QAAA,EAAU,QAAA;AAAA,EACV,UAAA,EACE,kHAAA;AAAA,EACF,2BAAA,EAA6B;AAAA,IAC3B,WAAA,EAAa;AAAA;AAEjB,CAAA,CAAE,CAAA;AAKK,MAAM,wBAAA,GAA2B,CAAC,EAAE,QAAA,EAAS,KAAyB;AAC3E,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,kBAAA;AAAA,MAAA;AAAA,QACC,MAAA,EAAM,IAAA;AAAA,QACN,SAAA,EAAW,sCAAA;AAAA,QACX,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,6BAAA,EAA2B,IAAA;AAAA,QAE3B,8BAAC,uBAAA,EAAA,EAAwB;AAAA;AAAA;AAC3B,GAAA,EAEJ,CAAA,EACF,CAAA;AAEJ;;;;"}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { useState, useEffect } from 'react';
|
|
1
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { useState, useEffect, useMemo, Fragment } from 'react';
|
|
3
3
|
import { styled } from '@mui/material/styles';
|
|
4
4
|
import Typography from '@mui/material/Typography';
|
|
5
5
|
import { MenuToggle, Dropdown, DropdownList, DropdownItem, Tooltip } from '@patternfly/react-core';
|
|
6
|
-
import { AngleDownIcon } from '@patternfly/react-icons';
|
|
6
|
+
import { OutlinedImageIcon, CheckIcon, AngleDownIcon } from '@patternfly/react-icons';
|
|
7
7
|
import { useTranslation } from '../hooks/useTranslation.esm.js';
|
|
8
8
|
|
|
9
9
|
const SelectorToggle = styled(MenuToggle)(({ theme }) => ({
|
|
@@ -26,10 +26,64 @@ const SelectorToggle = styled(MenuToggle)(({ theme }) => ({
|
|
|
26
26
|
opacity: 0.5
|
|
27
27
|
}
|
|
28
28
|
}));
|
|
29
|
+
const VisionIndicatorIcon = styled(OutlinedImageIcon)(({ theme }) => ({
|
|
30
|
+
width: 16,
|
|
31
|
+
height: 16,
|
|
32
|
+
color: theme.palette.text.secondary,
|
|
33
|
+
flexShrink: 0
|
|
34
|
+
}));
|
|
35
|
+
const VisionIndicatorWrap = styled("span")({
|
|
36
|
+
display: "inline-flex",
|
|
37
|
+
alignItems: "center",
|
|
38
|
+
lineHeight: 1
|
|
39
|
+
});
|
|
40
|
+
const VisionSlot = styled("span")({
|
|
41
|
+
display: "inline-flex",
|
|
42
|
+
alignItems: "center",
|
|
43
|
+
justifyContent: "center",
|
|
44
|
+
flexShrink: 0,
|
|
45
|
+
width: 16,
|
|
46
|
+
height: 16
|
|
47
|
+
});
|
|
48
|
+
const TickSlot = styled("span")(({ theme }) => ({
|
|
49
|
+
display: "inline-flex",
|
|
50
|
+
alignItems: "center",
|
|
51
|
+
justifyContent: "center",
|
|
52
|
+
flexShrink: 0,
|
|
53
|
+
width: "1em",
|
|
54
|
+
height: "1em",
|
|
55
|
+
color: theme.palette.primary.main
|
|
56
|
+
}));
|
|
57
|
+
const ModelLabel = styled("span")({
|
|
58
|
+
flex: "1 1 auto",
|
|
59
|
+
minWidth: 0,
|
|
60
|
+
overflow: "hidden",
|
|
61
|
+
textOverflow: "ellipsis",
|
|
62
|
+
whiteSpace: "nowrap"
|
|
63
|
+
});
|
|
64
|
+
const ModelItemContent = styled("span")({
|
|
65
|
+
display: "flex",
|
|
66
|
+
alignItems: "center",
|
|
67
|
+
gap: 8,
|
|
68
|
+
width: "100%",
|
|
69
|
+
minWidth: 0
|
|
70
|
+
});
|
|
29
71
|
const StyledDropdown = styled(Dropdown)({
|
|
30
72
|
"& ul, & li": {
|
|
31
73
|
padding: 0,
|
|
32
74
|
margin: 0
|
|
75
|
+
},
|
|
76
|
+
"& .pf-v6-c-menu__item-main": {
|
|
77
|
+
width: "100%"
|
|
78
|
+
},
|
|
79
|
+
"& .pf-v6-c-menu__item-text": {
|
|
80
|
+
flex: "1 1 auto",
|
|
81
|
+
minWidth: 0,
|
|
82
|
+
overflow: "hidden"
|
|
83
|
+
},
|
|
84
|
+
// We render our own fixed tick column; hide PF's conditional select icon.
|
|
85
|
+
"& .pf-v6-c-menu__item-select-icon": {
|
|
86
|
+
display: "none"
|
|
33
87
|
}
|
|
34
88
|
});
|
|
35
89
|
const MessageBarModelSelector = ({
|
|
@@ -47,6 +101,14 @@ const MessageBarModelSelector = ({
|
|
|
47
101
|
}
|
|
48
102
|
}, [disabled]);
|
|
49
103
|
const selectedModelLabel = models.find((m) => m.value === selectedModel)?.label ?? selectedModel;
|
|
104
|
+
const visionScreenshotTooltip = useMemo(
|
|
105
|
+
() => /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
106
|
+
t("modelSelector.visionScreenshot.line1"),
|
|
107
|
+
/* @__PURE__ */ jsx("br", {}),
|
|
108
|
+
t("modelSelector.visionScreenshot.line2")
|
|
109
|
+
] }),
|
|
110
|
+
[t]
|
|
111
|
+
);
|
|
50
112
|
const toggle = (toggleRef) => /* @__PURE__ */ jsxs(
|
|
51
113
|
SelectorToggle,
|
|
52
114
|
{
|
|
@@ -78,15 +140,45 @@ const MessageBarModelSelector = ({
|
|
|
78
140
|
toggle,
|
|
79
141
|
isScrollable: models.length > 10,
|
|
80
142
|
maxMenuHeight: models.length > 10 ? "240px" : void 0,
|
|
81
|
-
children: /* @__PURE__ */ jsx(DropdownList, { children: models.map((model) =>
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
143
|
+
children: /* @__PURE__ */ jsx(DropdownList, { children: models.map((model) => {
|
|
144
|
+
const isSelected = selectedModel === model.value;
|
|
145
|
+
return /* @__PURE__ */ jsx(
|
|
146
|
+
DropdownItem,
|
|
147
|
+
{
|
|
148
|
+
value: model.value,
|
|
149
|
+
isSelected,
|
|
150
|
+
children: /* @__PURE__ */ jsxs(ModelItemContent, { children: [
|
|
151
|
+
/* @__PURE__ */ jsx(ModelLabel, { title: model.label, children: model.label }),
|
|
152
|
+
model.supportsVision ? /* @__PURE__ */ jsx(VisionSlot, { className: "lightspeed-model-vision-slot", children: /* @__PURE__ */ jsx(Tooltip, { content: visionScreenshotTooltip, children: /* @__PURE__ */ jsx(
|
|
153
|
+
VisionIndicatorWrap,
|
|
154
|
+
{
|
|
155
|
+
"aria-label": t(
|
|
156
|
+
"modelSelector.visionScreenshot.ariaLabel"
|
|
157
|
+
),
|
|
158
|
+
onClick: (event) => event.stopPropagation(),
|
|
159
|
+
onMouseDown: (event) => event.stopPropagation(),
|
|
160
|
+
children: /* @__PURE__ */ jsx(VisionIndicatorIcon, { "aria-hidden": true })
|
|
161
|
+
}
|
|
162
|
+
) }) }) : /* @__PURE__ */ jsx(
|
|
163
|
+
VisionSlot,
|
|
164
|
+
{
|
|
165
|
+
className: "lightspeed-model-vision-slot",
|
|
166
|
+
"aria-hidden": true
|
|
167
|
+
}
|
|
168
|
+
),
|
|
169
|
+
/* @__PURE__ */ jsx(
|
|
170
|
+
TickSlot,
|
|
171
|
+
{
|
|
172
|
+
className: "lightspeed-model-tick-slot",
|
|
173
|
+
"aria-hidden": !isSelected,
|
|
174
|
+
children: isSelected ? /* @__PURE__ */ jsx(CheckIcon, { "aria-hidden": true }) : null
|
|
175
|
+
}
|
|
176
|
+
)
|
|
177
|
+
] })
|
|
178
|
+
},
|
|
179
|
+
model.value
|
|
180
|
+
);
|
|
181
|
+
}) })
|
|
90
182
|
}
|
|
91
183
|
);
|
|
92
184
|
if (disabled && disabledTooltip) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MessageBarModelSelector.esm.js","sources":["../../src/components/MessageBarModelSelector.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 { Ref, useEffect, useState } from 'react';\n\nimport { styled } from '@mui/material/styles';\nimport Typography from '@mui/material/Typography';\nimport {\n Dropdown,\n DropdownItem,\n DropdownList,\n MenuToggle,\n MenuToggleElement,\n Tooltip,\n} from '@patternfly/react-core';\nimport { AngleDownIcon } from '@patternfly/react-icons';\n\nimport { useTranslation } from '../hooks/useTranslation';\n\ntype MessageBarModelSelectorProps = {\n selectedModel: string;\n models: { label: string; value: string; provider: string }[];\n onSelect: (model: string) => void;\n disabled?: boolean;\n disabledTooltip?: string;\n};\n\nconst SelectorToggle = styled(MenuToggle)(({ theme }) => ({\n display: 'flex',\n alignItems: 'center',\n gap: 4,\n color: theme.palette.text.secondary,\n fontSize: 14,\n fontWeight: 500,\n cursor: 'pointer',\n padding: '4px 8px',\n borderRadius: 8,\n border: 'none',\n background: 'transparent',\n '&:hover': {\n backgroundColor: theme.palette.action.hover,\n },\n '&:disabled': {\n cursor: 'not-allowed',\n opacity: 0.5,\n },\n}));\n\nconst StyledDropdown = styled(Dropdown)({\n '& ul, & li': {\n padding: 0,\n margin: 0,\n },\n});\n\nexport const MessageBarModelSelector = ({\n selectedModel,\n models,\n onSelect,\n disabled = false,\n disabledTooltip,\n}: MessageBarModelSelectorProps) => {\n const [isOpen, setIsOpen] = useState(false);\n const { t } = useTranslation();\n\n useEffect(() => {\n if (disabled) {\n setIsOpen(false);\n }\n }, [disabled]);\n\n const selectedModelLabel =\n models.find(m => m.value === selectedModel)?.label ?? selectedModel;\n\n const toggle = (toggleRef: Ref<MenuToggleElement>) => (\n <SelectorToggle\n ref={toggleRef}\n onClick={() => setIsOpen(!isOpen)}\n isExpanded={isOpen}\n isDisabled={disabled}\n variant=\"plain\"\n aria-label={t('aria.chatbotSelector')}\n >\n {selectedModelLabel}\n <AngleDownIcon />\n </SelectorToggle>\n );\n\n const dropdown = (\n <StyledDropdown\n isOpen={isOpen && !disabled}\n onSelect={(_e, value) => {\n if (disabled) return;\n onSelect(value as string);\n setIsOpen(false);\n }}\n onOpenChange={open => setIsOpen(open)}\n popperProps={{ position: 'left' }}\n shouldFocusToggleOnSelect\n shouldFocusFirstItemOnOpen={false}\n toggle={toggle}\n isScrollable={models.length > 10}\n maxMenuHeight={models.length > 10 ? '240px' : undefined}\n >\n <DropdownList>\n {models.map(model => (\n <DropdownItem\n value={model.value}\n key={model.value}\n isSelected={selectedModel === model.value}\n >\n {model.label}\n </DropdownItem>\n ))}\n </DropdownList>\n </StyledDropdown>\n );\n\n if (disabled && disabledTooltip) {\n return (\n <Tooltip content={disabledTooltip}>\n <Typography component=\"span\">{dropdown}</Typography>\n </Tooltip>\n );\n }\n\n return dropdown;\n};\n"],"names":[],"mappings":";;;;;;;;AAwCA,MAAM,iBAAiB,MAAA,CAAO,UAAU,EAAE,CAAC,EAAE,OAAM,MAAO;AAAA,EACxD,OAAA,EAAS,MAAA;AAAA,EACT,UAAA,EAAY,QAAA;AAAA,EACZ,GAAA,EAAK,CAAA;AAAA,EACL,KAAA,EAAO,KAAA,CAAM,OAAA,CAAQ,IAAA,CAAK,SAAA;AAAA,EAC1B,QAAA,EAAU,EAAA;AAAA,EACV,UAAA,EAAY,GAAA;AAAA,EACZ,MAAA,EAAQ,SAAA;AAAA,EACR,OAAA,EAAS,SAAA;AAAA,EACT,YAAA,EAAc,CAAA;AAAA,EACd,MAAA,EAAQ,MAAA;AAAA,EACR,UAAA,EAAY,aAAA;AAAA,EACZ,SAAA,EAAW;AAAA,IACT,eAAA,EAAiB,KAAA,CAAM,OAAA,CAAQ,MAAA,CAAO;AAAA,GACxC;AAAA,EACA,YAAA,EAAc;AAAA,IACZ,MAAA,EAAQ,aAAA;AAAA,IACR,OAAA,EAAS;AAAA;AAEb,CAAA,CAAE,CAAA;AAEF,MAAM,cAAA,GAAiB,MAAA,CAAO,QAAQ,CAAA,CAAE;AAAA,EACtC,YAAA,EAAc;AAAA,IACZ,OAAA,EAAS,CAAA;AAAA,IACT,MAAA,EAAQ;AAAA;AAEZ,CAAC,CAAA;AAEM,MAAM,0BAA0B,CAAC;AAAA,EACtC,aAAA;AAAA,EACA,MAAA;AAAA,EACA,QAAA;AAAA,EACA,QAAA,GAAW,KAAA;AAAA,EACX;AACF,CAAA,KAAoC;AAClC,EAAA,MAAM,CAAC,MAAA,EAAQ,SAAS,CAAA,GAAI,SAAS,KAAK,CAAA;AAC1C,EAAA,MAAM,EAAE,CAAA,EAAE,GAAI,cAAA,EAAe;AAE7B,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,QAAA,EAAU;AACZ,MAAA,SAAA,CAAU,KAAK,CAAA;AAAA,IACjB;AAAA,EACF,CAAA,EAAG,CAAC,QAAQ,CAAC,CAAA;AAEb,EAAA,MAAM,kBAAA,GACJ,OAAO,IAAA,CAAK,CAAA,CAAA,KAAK,EAAE,KAAA,KAAU,aAAa,GAAG,KAAA,IAAS,aAAA;AAExD,EAAA,MAAM,MAAA,GAAS,CAAC,SAAA,qBACd,IAAA;AAAA,IAAC,cAAA;AAAA,IAAA;AAAA,MACC,GAAA,EAAK,SAAA;AAAA,MACL,OAAA,EAAS,MAAM,SAAA,CAAU,CAAC,MAAM,CAAA;AAAA,MAChC,UAAA,EAAY,MAAA;AAAA,MACZ,UAAA,EAAY,QAAA;AAAA,MACZ,OAAA,EAAQ,OAAA;AAAA,MACR,YAAA,EAAY,EAAE,sBAAsB,CAAA;AAAA,MAEnC,QAAA,EAAA;AAAA,QAAA,kBAAA;AAAA,4BACA,aAAA,EAAA,EAAc;AAAA;AAAA;AAAA,GACjB;AAGF,EAAA,MAAM,QAAA,mBACJ,GAAA;AAAA,IAAC,cAAA;AAAA,IAAA;AAAA,MACC,MAAA,EAAQ,UAAU,CAAC,QAAA;AAAA,MACnB,QAAA,EAAU,CAAC,EAAA,EAAI,KAAA,KAAU;AACvB,QAAA,IAAI,QAAA,EAAU;AACd,QAAA,QAAA,CAAS,KAAe,CAAA;AACxB,QAAA,SAAA,CAAU,KAAK,CAAA;AAAA,MACjB,CAAA;AAAA,MACA,YAAA,EAAc,CAAA,IAAA,KAAQ,SAAA,CAAU,IAAI,CAAA;AAAA,MACpC,WAAA,EAAa,EAAE,QAAA,EAAU,MAAA,EAAO;AAAA,MAChC,yBAAA,EAAyB,IAAA;AAAA,MACzB,0BAAA,EAA4B,KAAA;AAAA,MAC5B,MAAA;AAAA,MACA,YAAA,EAAc,OAAO,MAAA,GAAS,EAAA;AAAA,MAC9B,aAAA,EAAe,MAAA,CAAO,MAAA,GAAS,EAAA,GAAK,OAAA,GAAU,MAAA;AAAA,MAE9C,QAAA,kBAAA,GAAA,CAAC,YAAA,EAAA,EACE,QAAA,EAAA,MAAA,CAAO,GAAA,CAAI,CAAA,KAAA,qBACV,GAAA;AAAA,QAAC,YAAA;AAAA,QAAA;AAAA,UACC,OAAO,KAAA,CAAM,KAAA;AAAA,UAEb,UAAA,EAAY,kBAAkB,KAAA,CAAM,KAAA;AAAA,UAEnC,QAAA,EAAA,KAAA,CAAM;AAAA,SAAA;AAAA,QAHF,KAAA,CAAM;AAAA,OAKd,CAAA,EACH;AAAA;AAAA,GACF;AAGF,EAAA,IAAI,YAAY,eAAA,EAAiB;AAC/B,IAAA,uBACE,GAAA,CAAC,WAAQ,OAAA,EAAS,eAAA,EAChB,8BAAC,UAAA,EAAA,EAAW,SAAA,EAAU,MAAA,EAAQ,QAAA,EAAA,QAAA,EAAS,CAAA,EACzC,CAAA;AAAA,EAEJ;AAEA,EAAA,OAAO,QAAA;AACT;;;;"}
|
|
1
|
+
{"version":3,"file":"MessageBarModelSelector.esm.js","sources":["../../src/components/MessageBarModelSelector.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 { Fragment, Ref, useEffect, useMemo, useState } from 'react';\n\nimport { styled } from '@mui/material/styles';\nimport Typography from '@mui/material/Typography';\nimport {\n Dropdown,\n DropdownItem,\n DropdownList,\n MenuToggle,\n MenuToggleElement,\n Tooltip,\n} from '@patternfly/react-core';\nimport {\n AngleDownIcon,\n CheckIcon,\n OutlinedImageIcon,\n} from '@patternfly/react-icons';\n\nimport { useTranslation } from '../hooks/useTranslation';\n\ntype MessageBarModelSelectorProps = {\n selectedModel: string;\n models: {\n label: string;\n value: string;\n provider: string;\n supportsVision?: boolean;\n }[];\n onSelect: (model: string) => void;\n disabled?: boolean;\n disabledTooltip?: string;\n};\n\nconst SelectorToggle = styled(MenuToggle)(({ theme }) => ({\n display: 'flex',\n alignItems: 'center',\n gap: 4,\n color: theme.palette.text.secondary,\n fontSize: 14,\n fontWeight: 500,\n cursor: 'pointer',\n padding: '4px 8px',\n borderRadius: 8,\n border: 'none',\n background: 'transparent',\n '&:hover': {\n backgroundColor: theme.palette.action.hover,\n },\n '&:disabled': {\n cursor: 'not-allowed',\n opacity: 0.5,\n },\n}));\n\nconst VisionIndicatorIcon = styled(OutlinedImageIcon)(({ theme }) => ({\n width: 16,\n height: 16,\n color: theme.palette.text.secondary,\n flexShrink: 0,\n}));\n\nconst VisionIndicatorWrap = styled('span')({\n display: 'inline-flex',\n alignItems: 'center',\n lineHeight: 1,\n});\n\n/** Fixed-width slot so vision icons align across rows (empty when unsupported). */\nconst VisionSlot = styled('span')({\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n flexShrink: 0,\n width: 16,\n height: 16,\n});\n\n/** Fixed-width slot so the select tick aligns across rows (empty when not selected). */\nconst TickSlot = styled('span')(({ theme }) => ({\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n flexShrink: 0,\n width: '1em',\n height: '1em',\n color: theme.palette.primary.main,\n}));\n\nconst ModelLabel = styled('span')({\n flex: '1 1 auto',\n minWidth: 0,\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n});\n\nconst ModelItemContent = styled('span')({\n display: 'flex',\n alignItems: 'center',\n gap: 8,\n width: '100%',\n minWidth: 0,\n});\n\nconst StyledDropdown = styled(Dropdown)({\n '& ul, & li': {\n padding: 0,\n margin: 0,\n },\n '& .pf-v6-c-menu__item-main': {\n width: '100%',\n },\n '& .pf-v6-c-menu__item-text': {\n flex: '1 1 auto',\n minWidth: 0,\n overflow: 'hidden',\n },\n // We render our own fixed tick column; hide PF's conditional select icon.\n '& .pf-v6-c-menu__item-select-icon': {\n display: 'none',\n },\n});\n\nexport const MessageBarModelSelector = ({\n selectedModel,\n models,\n onSelect,\n disabled = false,\n disabledTooltip,\n}: MessageBarModelSelectorProps) => {\n const [isOpen, setIsOpen] = useState(false);\n const { t } = useTranslation();\n\n useEffect(() => {\n if (disabled) {\n setIsOpen(false);\n }\n }, [disabled]);\n\n const selectedModelLabel =\n models.find(m => m.value === selectedModel)?.label ?? selectedModel;\n\n const visionScreenshotTooltip = useMemo(\n () => (\n <Fragment>\n {t('modelSelector.visionScreenshot.line1')}\n <br />\n {t('modelSelector.visionScreenshot.line2')}\n </Fragment>\n ),\n [t],\n );\n\n const toggle = (toggleRef: Ref<MenuToggleElement>) => (\n <SelectorToggle\n ref={toggleRef}\n onClick={() => setIsOpen(!isOpen)}\n isExpanded={isOpen}\n isDisabled={disabled}\n variant=\"plain\"\n aria-label={t('aria.chatbotSelector')}\n >\n {selectedModelLabel}\n <AngleDownIcon />\n </SelectorToggle>\n );\n\n const dropdown = (\n <StyledDropdown\n isOpen={isOpen && !disabled}\n onSelect={(_e, value) => {\n if (disabled) return;\n onSelect(value as string);\n setIsOpen(false);\n }}\n onOpenChange={open => setIsOpen(open)}\n popperProps={{ position: 'left' }}\n shouldFocusToggleOnSelect\n shouldFocusFirstItemOnOpen={false}\n toggle={toggle}\n isScrollable={models.length > 10}\n maxMenuHeight={models.length > 10 ? '240px' : undefined}\n >\n <DropdownList>\n {models.map(model => {\n const isSelected = selectedModel === model.value;\n return (\n <DropdownItem\n value={model.value}\n key={model.value}\n isSelected={isSelected}\n >\n <ModelItemContent>\n <ModelLabel title={model.label}>{model.label}</ModelLabel>\n {model.supportsVision ? (\n <VisionSlot className=\"lightspeed-model-vision-slot\">\n <Tooltip content={visionScreenshotTooltip}>\n <VisionIndicatorWrap\n aria-label={t(\n 'modelSelector.visionScreenshot.ariaLabel',\n )}\n onClick={event => event.stopPropagation()}\n onMouseDown={event => event.stopPropagation()}\n >\n <VisionIndicatorIcon aria-hidden />\n </VisionIndicatorWrap>\n </Tooltip>\n </VisionSlot>\n ) : (\n <VisionSlot\n className=\"lightspeed-model-vision-slot\"\n aria-hidden\n />\n )}\n <TickSlot\n className=\"lightspeed-model-tick-slot\"\n aria-hidden={!isSelected}\n >\n {isSelected ? <CheckIcon aria-hidden /> : null}\n </TickSlot>\n </ModelItemContent>\n </DropdownItem>\n );\n })}\n </DropdownList>\n </StyledDropdown>\n );\n\n if (disabled && disabledTooltip) {\n return (\n <Tooltip content={disabledTooltip}>\n <Typography component=\"span\">{dropdown}</Typography>\n </Tooltip>\n );\n }\n\n return dropdown;\n};\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { useMemo, Fragment } from 'react';
|
|
3
|
+
import { keyframes, styled } from '@mui/material/styles';
|
|
4
|
+
import { Label, Tooltip } from '@patternfly/react-core';
|
|
5
|
+
import { PauseIcon } from '@patternfly/react-icons';
|
|
6
|
+
import { useScreenContextLabelRevision } from '../hooks/useScreenContextLabelRevision.esm.js';
|
|
7
|
+
import { useTranslation } from '../hooks/useTranslation.esm.js';
|
|
8
|
+
import { useWindowLocation } from '../hooks/useWindowLocation.esm.js';
|
|
9
|
+
import { resolveScreenContextChipLabel, SOFTWARE_TEMPLATES_LIST_CHIP_LABEL, getScreenContextTooltipLine1Text, getScreenContextTooltipLine2Key } from '../utils/screen-context-utils.esm.js';
|
|
10
|
+
|
|
11
|
+
const CHIP_MAX_WIDTH_PX = 150;
|
|
12
|
+
const CHIP_HEIGHT_PX = 24;
|
|
13
|
+
const pulse = keyframes`
|
|
14
|
+
0% { opacity: 0.45; transform: scale(0.92); }
|
|
15
|
+
50% { opacity: 1; transform: scale(1); }
|
|
16
|
+
100% { opacity: 0.45; transform: scale(0.92); }
|
|
17
|
+
`;
|
|
18
|
+
const ChipWrap = styled("div")({
|
|
19
|
+
display: "inline-flex",
|
|
20
|
+
height: CHIP_HEIGHT_PX,
|
|
21
|
+
maxWidth: CHIP_MAX_WIDTH_PX,
|
|
22
|
+
minWidth: 0,
|
|
23
|
+
flexShrink: 0
|
|
24
|
+
});
|
|
25
|
+
const FixedSizeChipLabel = styled(Label)({
|
|
26
|
+
height: CHIP_HEIGHT_PX,
|
|
27
|
+
maxWidth: CHIP_MAX_WIDTH_PX,
|
|
28
|
+
width: "max-content",
|
|
29
|
+
boxSizing: "border-box",
|
|
30
|
+
display: "inline-flex",
|
|
31
|
+
alignItems: "center",
|
|
32
|
+
flexShrink: 0,
|
|
33
|
+
"--pf-v6-c-label--PaddingBlockStart": "0",
|
|
34
|
+
"--pf-v6-c-label--PaddingBlockEnd": "0",
|
|
35
|
+
"--pf-v6-c-label--MinWidth": "auto",
|
|
36
|
+
"& .pf-v6-c-label__content": {
|
|
37
|
+
maxWidth: "100%",
|
|
38
|
+
height: "100%",
|
|
39
|
+
minWidth: 0,
|
|
40
|
+
boxSizing: "border-box"
|
|
41
|
+
},
|
|
42
|
+
"& .pf-v6-c-label__text": {
|
|
43
|
+
overflow: "hidden",
|
|
44
|
+
textOverflow: "ellipsis",
|
|
45
|
+
whiteSpace: "nowrap",
|
|
46
|
+
minWidth: 0
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
const RecordingDot = styled("span")({
|
|
50
|
+
display: "inline-block",
|
|
51
|
+
width: 8,
|
|
52
|
+
height: 8,
|
|
53
|
+
borderRadius: "50%",
|
|
54
|
+
backgroundColor: "var(--pf-t--global--icon--color--status--danger--default)",
|
|
55
|
+
animation: `${pulse} 1.4s ease-in-out infinite`
|
|
56
|
+
});
|
|
57
|
+
const ChipText = styled("span")({
|
|
58
|
+
overflow: "hidden",
|
|
59
|
+
textOverflow: "ellipsis",
|
|
60
|
+
whiteSpace: "nowrap",
|
|
61
|
+
minWidth: 0
|
|
62
|
+
});
|
|
63
|
+
const LINE2_I18N = {
|
|
64
|
+
fullContext: "contextChip.tooltip.line2.fullContext",
|
|
65
|
+
adminLimited: "contextChip.tooltip.line2.adminLimited",
|
|
66
|
+
screenshotOnly: "contextChip.tooltip.line2.screenshotOnly",
|
|
67
|
+
domOffNoVision: "contextChip.tooltip.line2.domOffNoVision",
|
|
68
|
+
textOnlyNoVision: "contextChip.tooltip.line2.textOnlyNoVision",
|
|
69
|
+
textOnlyAdminScreenshotsOff: "contextChip.tooltip.line2.textOnlyAdminScreenshotsOff",
|
|
70
|
+
textOnlyCombined: "contextChip.tooltip.line2.textOnlyCombined"
|
|
71
|
+
};
|
|
72
|
+
const ScreenContextChip = ({
|
|
73
|
+
state,
|
|
74
|
+
chipLabel,
|
|
75
|
+
domEnabled,
|
|
76
|
+
screenshotsEnabled,
|
|
77
|
+
supportsVision,
|
|
78
|
+
onTogglePaused
|
|
79
|
+
}) => {
|
|
80
|
+
const { t } = useTranslation();
|
|
81
|
+
const { pathname, search } = useWindowLocation();
|
|
82
|
+
useScreenContextLabelRevision();
|
|
83
|
+
const { label: resolvedLabel, routeKind } = resolveScreenContextChipLabel({
|
|
84
|
+
pathname,
|
|
85
|
+
search
|
|
86
|
+
});
|
|
87
|
+
const label = chipLabel ?? resolvedLabel;
|
|
88
|
+
const displayLabel = label === SOFTWARE_TEMPLATES_LIST_CHIP_LABEL ? t("contextChip.label.softwareTemplates") : label;
|
|
89
|
+
const tooltipContent = useMemo(() => {
|
|
90
|
+
if (state === "unavailable") {
|
|
91
|
+
return t("contextChip.tooltip.unavailable");
|
|
92
|
+
}
|
|
93
|
+
if (state === "paused") {
|
|
94
|
+
return t("contextChip.tooltip.paused");
|
|
95
|
+
}
|
|
96
|
+
const line1 = getScreenContextTooltipLine1Text(
|
|
97
|
+
{
|
|
98
|
+
chipLabel: displayLabel,
|
|
99
|
+
routeKind,
|
|
100
|
+
pathname
|
|
101
|
+
},
|
|
102
|
+
(key, options) => t(key, options)
|
|
103
|
+
);
|
|
104
|
+
const line2Key = getScreenContextTooltipLine2Key({
|
|
105
|
+
domEnabled,
|
|
106
|
+
screenshotsEnabled,
|
|
107
|
+
supportsVision
|
|
108
|
+
});
|
|
109
|
+
const line2 = t(LINE2_I18N[line2Key], {});
|
|
110
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
111
|
+
line1,
|
|
112
|
+
/* @__PURE__ */ jsx("br", {}),
|
|
113
|
+
line2
|
|
114
|
+
] });
|
|
115
|
+
}, [
|
|
116
|
+
state,
|
|
117
|
+
displayLabel,
|
|
118
|
+
routeKind,
|
|
119
|
+
pathname,
|
|
120
|
+
domEnabled,
|
|
121
|
+
screenshotsEnabled,
|
|
122
|
+
supportsVision,
|
|
123
|
+
t
|
|
124
|
+
]);
|
|
125
|
+
if (state === "unavailable") {
|
|
126
|
+
return /* @__PURE__ */ jsx(ChipWrap, { className: "lightspeed-page-context-label lightspeed-page-context-label-unavailable", children: /* @__PURE__ */ jsx(Tooltip, { content: tooltipContent, children: /* @__PURE__ */ jsx(
|
|
127
|
+
FixedSizeChipLabel,
|
|
128
|
+
{
|
|
129
|
+
color: "grey",
|
|
130
|
+
variant: "outline",
|
|
131
|
+
isCompact: true,
|
|
132
|
+
className: "lightspeed-context-chip-unavailable-label",
|
|
133
|
+
children: /* @__PURE__ */ jsx(ChipText, { children: t("contextChip.label.unavailable") })
|
|
134
|
+
}
|
|
135
|
+
) }) });
|
|
136
|
+
}
|
|
137
|
+
if (state === "paused") {
|
|
138
|
+
return /* @__PURE__ */ jsx(ChipWrap, { className: "lightspeed-page-context-label lightspeed-page-context-label-paused", children: /* @__PURE__ */ jsx(Tooltip, { content: tooltipContent, children: /* @__PURE__ */ jsx(
|
|
139
|
+
FixedSizeChipLabel,
|
|
140
|
+
{
|
|
141
|
+
color: "grey",
|
|
142
|
+
variant: "outline",
|
|
143
|
+
isCompact: true,
|
|
144
|
+
isClickable: true,
|
|
145
|
+
onClick: onTogglePaused,
|
|
146
|
+
icon: /* @__PURE__ */ jsx(PauseIcon, { "aria-hidden": true }),
|
|
147
|
+
className: "lightspeed-page-context-chip-clickable lightspeed-context-chip-paused-label",
|
|
148
|
+
"aria-label": t("contextChip.aria.resume"),
|
|
149
|
+
children: /* @__PURE__ */ jsx(ChipText, { children: t("contextChip.label.paused") })
|
|
150
|
+
}
|
|
151
|
+
) }) });
|
|
152
|
+
}
|
|
153
|
+
return /* @__PURE__ */ jsx(ChipWrap, { className: "lightspeed-page-context-label lightspeed-page-context-label-recording lightspeed-page-context-chip-clickable", children: /* @__PURE__ */ jsx(Tooltip, { content: tooltipContent, children: /* @__PURE__ */ jsx(
|
|
154
|
+
FixedSizeChipLabel,
|
|
155
|
+
{
|
|
156
|
+
color: "red",
|
|
157
|
+
variant: "outline",
|
|
158
|
+
isCompact: true,
|
|
159
|
+
isClickable: true,
|
|
160
|
+
onClick: onTogglePaused,
|
|
161
|
+
icon: /* @__PURE__ */ jsx(RecordingDot, { "aria-hidden": true }),
|
|
162
|
+
className: "lightspeed-context-chip-recording-label",
|
|
163
|
+
"aria-label": t("contextChip.aria.pause", {
|
|
164
|
+
label: displayLabel
|
|
165
|
+
}),
|
|
166
|
+
children: /* @__PURE__ */ jsx(ChipText, { children: displayLabel })
|
|
167
|
+
}
|
|
168
|
+
) }) });
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
export { ScreenContextChip };
|
|
172
|
+
//# sourceMappingURL=ScreenContextChip.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ScreenContextChip.esm.js","sources":["../../src/components/ScreenContextChip.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 { Fragment, useMemo } from 'react';\n\nimport { keyframes, styled } from '@mui/material/styles';\nimport { Label, Tooltip } from '@patternfly/react-core';\nimport { PauseIcon } from '@patternfly/react-icons';\n\nimport { useScreenContextLabelRevision } from '../hooks/useScreenContextLabelRevision';\nimport { useTranslation } from '../hooks/useTranslation';\nimport { useWindowLocation } from '../hooks/useWindowLocation';\nimport {\n getScreenContextTooltipLine1Text,\n getScreenContextTooltipLine2Key,\n resolveScreenContextChipLabel,\n ScreenContextTooltipLine2Key,\n SOFTWARE_TEMPLATES_LIST_CHIP_LABEL,\n} from '../utils/screen-context-utils';\n\nexport type ScreenContextChipState = 'recording' | 'paused' | 'unavailable';\n\n/** Prototype max width; shorter labels shrink to content. */\nconst CHIP_MAX_WIDTH_PX = 150;\nconst CHIP_HEIGHT_PX = 24;\n\nconst pulse = keyframes`\n 0% { opacity: 0.45; transform: scale(0.92); }\n 50% { opacity: 1; transform: scale(1); }\n 100% { opacity: 0.45; transform: scale(0.92); }\n`;\n\nconst ChipWrap = styled('div')({\n display: 'inline-flex',\n height: CHIP_HEIGHT_PX,\n maxWidth: CHIP_MAX_WIDTH_PX,\n minWidth: 0,\n flexShrink: 0,\n});\n\nconst FixedSizeChipLabel = styled(Label)({\n height: CHIP_HEIGHT_PX,\n maxWidth: CHIP_MAX_WIDTH_PX,\n width: 'max-content',\n boxSizing: 'border-box',\n display: 'inline-flex',\n alignItems: 'center',\n flexShrink: 0,\n '--pf-v6-c-label--PaddingBlockStart': '0',\n '--pf-v6-c-label--PaddingBlockEnd': '0',\n '--pf-v6-c-label--MinWidth': 'auto',\n '& .pf-v6-c-label__content': {\n maxWidth: '100%',\n height: '100%',\n minWidth: 0,\n boxSizing: 'border-box',\n },\n '& .pf-v6-c-label__text': {\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n minWidth: 0,\n },\n});\n\nconst RecordingDot = styled('span')({\n display: 'inline-block',\n width: 8,\n height: 8,\n borderRadius: '50%',\n backgroundColor: 'var(--pf-t--global--icon--color--status--danger--default)',\n animation: `${pulse} 1.4s ease-in-out infinite`,\n});\n\nconst ChipText = styled('span')({\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n minWidth: 0,\n});\n\nconst LINE2_I18N: Record<ScreenContextTooltipLine2Key, string> = {\n fullContext: 'contextChip.tooltip.line2.fullContext',\n adminLimited: 'contextChip.tooltip.line2.adminLimited',\n screenshotOnly: 'contextChip.tooltip.line2.screenshotOnly',\n domOffNoVision: 'contextChip.tooltip.line2.domOffNoVision',\n textOnlyNoVision: 'contextChip.tooltip.line2.textOnlyNoVision',\n textOnlyAdminScreenshotsOff:\n 'contextChip.tooltip.line2.textOnlyAdminScreenshotsOff',\n textOnlyCombined: 'contextChip.tooltip.line2.textOnlyCombined',\n};\n\nexport type ScreenContextChipProps = {\n state: ScreenContextChipState;\n chipLabel?: string;\n domEnabled: boolean;\n screenshotsEnabled: boolean;\n supportsVision: boolean;\n onTogglePaused?: () => void;\n};\n\nexport const ScreenContextChip = ({\n state,\n chipLabel,\n domEnabled,\n screenshotsEnabled,\n supportsVision,\n onTogglePaused,\n}: ScreenContextChipProps) => {\n const { t } = useTranslation();\n const { pathname, search } = useWindowLocation();\n useScreenContextLabelRevision();\n\n const { label: resolvedLabel, routeKind } = resolveScreenContextChipLabel({\n pathname,\n search,\n });\n\n const label = chipLabel ?? resolvedLabel;\n const displayLabel =\n label === SOFTWARE_TEMPLATES_LIST_CHIP_LABEL\n ? t('contextChip.label.softwareTemplates')\n : label;\n\n const tooltipContent = useMemo(() => {\n if (state === 'unavailable') {\n return t('contextChip.tooltip.unavailable');\n }\n if (state === 'paused') {\n return t('contextChip.tooltip.paused');\n }\n\n const line1 = getScreenContextTooltipLine1Text(\n {\n chipLabel: displayLabel,\n routeKind,\n pathname,\n },\n (key, options) => t(key as any, options as any),\n );\n const line2Key = getScreenContextTooltipLine2Key({\n domEnabled,\n screenshotsEnabled,\n supportsVision,\n });\n const line2 = t(LINE2_I18N[line2Key] as any, {} as any);\n return (\n <Fragment>\n {line1}\n <br />\n {line2}\n </Fragment>\n );\n }, [\n state,\n displayLabel,\n routeKind,\n pathname,\n domEnabled,\n screenshotsEnabled,\n supportsVision,\n t,\n ]);\n\n if (state === 'unavailable') {\n return (\n <ChipWrap className=\"lightspeed-page-context-label lightspeed-page-context-label-unavailable\">\n <Tooltip content={tooltipContent}>\n <FixedSizeChipLabel\n color=\"grey\"\n variant=\"outline\"\n isCompact\n className=\"lightspeed-context-chip-unavailable-label\"\n >\n <ChipText>{t('contextChip.label.unavailable')}</ChipText>\n </FixedSizeChipLabel>\n </Tooltip>\n </ChipWrap>\n );\n }\n\n if (state === 'paused') {\n return (\n <ChipWrap className=\"lightspeed-page-context-label lightspeed-page-context-label-paused\">\n <Tooltip content={tooltipContent}>\n <FixedSizeChipLabel\n color=\"grey\"\n variant=\"outline\"\n isCompact\n isClickable\n onClick={onTogglePaused}\n icon={<PauseIcon aria-hidden />}\n className=\"lightspeed-page-context-chip-clickable lightspeed-context-chip-paused-label\"\n aria-label={t('contextChip.aria.resume')}\n >\n <ChipText>{t('contextChip.label.paused')}</ChipText>\n </FixedSizeChipLabel>\n </Tooltip>\n </ChipWrap>\n );\n }\n\n return (\n <ChipWrap className=\"lightspeed-page-context-label lightspeed-page-context-label-recording lightspeed-page-context-chip-clickable\">\n <Tooltip content={tooltipContent}>\n <FixedSizeChipLabel\n color=\"red\"\n variant=\"outline\"\n isCompact\n isClickable\n onClick={onTogglePaused}\n icon={<RecordingDot aria-hidden />}\n className=\"lightspeed-context-chip-recording-label\"\n aria-label={t('contextChip.aria.pause' as any, {\n label: displayLabel,\n })}\n >\n <ChipText>{displayLabel}</ChipText>\n </FixedSizeChipLabel>\n </Tooltip>\n </ChipWrap>\n );\n};\n"],"names":[],"mappings":"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"}
|