@red-hat-developer-hub/backstage-plugin-intelligent-assistant 5.1.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.
Files changed (87) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/README.md +40 -5
  3. package/dist/alpha.d.ts +61 -0
  4. package/dist/api/LightspeedApiClient.esm.js +57 -0
  5. package/dist/api/LightspeedApiClient.esm.js.map +1 -1
  6. package/dist/api/api.esm.js.map +1 -1
  7. package/dist/components/DeleteModal.esm.js +2 -0
  8. package/dist/components/DeleteModal.esm.js.map +1 -1
  9. package/dist/components/DeleteSavedPromptModal.esm.js +75 -0
  10. package/dist/components/DeleteSavedPromptModal.esm.js.map +1 -0
  11. package/dist/components/LightSpeedChat.esm.js +276 -134
  12. package/dist/components/LightSpeedChat.esm.js.map +1 -1
  13. package/dist/components/LightspeedChatBoxHeader.esm.js +57 -2
  14. package/dist/components/LightspeedChatBoxHeader.esm.js.map +1 -1
  15. package/dist/components/LightspeedChatContainer.esm.js +2 -1
  16. package/dist/components/LightspeedChatContainer.esm.js.map +1 -1
  17. package/dist/components/LightspeedDrawerContext.esm.js.map +1 -1
  18. package/dist/components/LightspeedDrawerProvider.esm.js +1 -0
  19. package/dist/components/LightspeedDrawerProvider.esm.js.map +1 -1
  20. package/dist/components/McpServersSettings.esm.js +9 -22
  21. package/dist/components/McpServersSettings.esm.js.map +1 -1
  22. package/dist/components/MessageBarModelSelector.esm.js +104 -12
  23. package/dist/components/MessageBarModelSelector.esm.js.map +1 -1
  24. package/dist/components/SavedPromptCard.esm.js +100 -0
  25. package/dist/components/SavedPromptCard.esm.js.map +1 -0
  26. package/dist/components/SavedPromptKebabMenu.esm.js +87 -0
  27. package/dist/components/SavedPromptKebabMenu.esm.js.map +1 -0
  28. package/dist/components/SavedPromptMenuItems.esm.js +52 -0
  29. package/dist/components/SavedPromptMenuItems.esm.js.map +1 -0
  30. package/dist/components/SavedPromptsEmptyState.esm.js +63 -0
  31. package/dist/components/SavedPromptsEmptyState.esm.js.map +1 -0
  32. package/dist/components/SavedPromptsList.esm.js +63 -0
  33. package/dist/components/SavedPromptsList.esm.js.map +1 -0
  34. package/dist/components/SavedPromptsSettings.esm.js +285 -0
  35. package/dist/components/SavedPromptsSettings.esm.js.map +1 -0
  36. package/dist/components/ScreenContextChip.esm.js +172 -0
  37. package/dist/components/ScreenContextChip.esm.js.map +1 -0
  38. package/dist/components/SettingsPanel.esm.js +135 -0
  39. package/dist/components/SettingsPanel.esm.js.map +1 -0
  40. package/dist/hooks/screenContextLabelSubscription.esm.js +113 -0
  41. package/dist/hooks/screenContextLabelSubscription.esm.js.map +1 -0
  42. package/dist/hooks/useConversationHistoryGroups.esm.js +71 -0
  43. package/dist/hooks/useConversationHistoryGroups.esm.js.map +1 -0
  44. package/dist/hooks/useFeedbackActions.esm.js.map +1 -1
  45. package/dist/hooks/useLightspeedProviderState.esm.js +19 -5
  46. package/dist/hooks/useLightspeedProviderState.esm.js.map +1 -1
  47. package/dist/hooks/useSavedPromptActions.esm.js +64 -0
  48. package/dist/hooks/useSavedPromptActions.esm.js.map +1 -0
  49. package/dist/hooks/useSavedPrompts.esm.js +75 -0
  50. package/dist/hooks/useSavedPrompts.esm.js.map +1 -0
  51. package/dist/hooks/useSavedPromptsSettings.esm.js +65 -0
  52. package/dist/hooks/useSavedPromptsSettings.esm.js.map +1 -0
  53. package/dist/hooks/useScreenContextLabelRevision.esm.js +13 -0
  54. package/dist/hooks/useScreenContextLabelRevision.esm.js.map +1 -0
  55. package/dist/hooks/useScreenContextSettings.esm.js +110 -0
  56. package/dist/hooks/useScreenContextSettings.esm.js.map +1 -0
  57. package/dist/hooks/useSettingsPanelUrlState.esm.js +95 -0
  58. package/dist/hooks/useSettingsPanelUrlState.esm.js.map +1 -0
  59. package/dist/hooks/useWelcomePrompts.esm.js +16 -5
  60. package/dist/hooks/useWelcomePrompts.esm.js.map +1 -1
  61. package/dist/hooks/useWindowLocation.esm.js +28 -0
  62. package/dist/hooks/useWindowLocation.esm.js.map +1 -0
  63. package/dist/translations/de.esm.js +64 -1
  64. package/dist/translations/de.esm.js.map +1 -1
  65. package/dist/translations/es.esm.js +64 -1
  66. package/dist/translations/es.esm.js.map +1 -1
  67. package/dist/translations/fr.esm.js +64 -1
  68. package/dist/translations/fr.esm.js.map +1 -1
  69. package/dist/translations/it.esm.js +64 -1
  70. package/dist/translations/it.esm.js.map +1 -1
  71. package/dist/translations/ja.esm.js +64 -1
  72. package/dist/translations/ja.esm.js.map +1 -1
  73. package/dist/translations/ref.esm.js +64 -2
  74. package/dist/translations/ref.esm.js.map +1 -1
  75. package/dist/utils/buildConversationHistoryGroups.esm.js +241 -0
  76. package/dist/utils/buildConversationHistoryGroups.esm.js.map +1 -0
  77. package/dist/utils/dom-selectors.esm.js +22 -2
  78. package/dist/utils/dom-selectors.esm.js.map +1 -1
  79. package/dist/utils/prompt-utils.esm.js +18 -1
  80. package/dist/utils/prompt-utils.esm.js.map +1 -1
  81. package/dist/utils/screen-capture.esm.js +116 -0
  82. package/dist/utils/screen-capture.esm.js.map +1 -0
  83. package/dist/utils/screen-context-utils.esm.js +343 -0
  84. package/dist/utils/screen-context-utils.esm.js.map +1 -0
  85. package/dist/utils/sensitive-data-redactor.esm.js +39 -1
  86. package/dist/utils/sensitive-data-redactor.esm.js.map +1 -1
  87. package/package.json +5 -15
@@ -1,9 +1,9 @@
1
- import { jsx, jsxs } from 'react/jsx-runtime';
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) => /* @__PURE__ */ jsx(
82
- DropdownItem,
83
- {
84
- value: model.value,
85
- isSelected: selectedModel === model.value,
86
- children: model.label
87
- },
88
- model.value
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":"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"}
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,100 @@
1
+ import { jsx, jsxs } from 'react/jsx-runtime';
2
+ import { Tooltip, Content, ContentVariants } from '@patternfly/react-core';
3
+ import { makeStyles } from 'tss-react/mui';
4
+ import { SavedPromptKebabMenu } from './SavedPromptKebabMenu.esm.js';
5
+
6
+ const useStyles = makeStyles()((theme) => ({
7
+ card: {
8
+ padding: `${theme.spacing(1.5)} 0`
9
+ },
10
+ cardDivider: {
11
+ borderBottom: "1px solid var(--pf-t--global--border--color--default)"
12
+ },
13
+ row: {
14
+ display: "flex",
15
+ alignItems: "flex-start"
16
+ },
17
+ content: {
18
+ flex: "1 1 0%",
19
+ minWidth: 0
20
+ },
21
+ title: {
22
+ display: "block",
23
+ minWidth: 0,
24
+ maxWidth: "100%",
25
+ margin: 0,
26
+ marginBottom: theme.spacing(0.5),
27
+ fontWeight: 600,
28
+ overflow: "hidden",
29
+ textOverflow: "ellipsis",
30
+ whiteSpace: "nowrap"
31
+ },
32
+ body: {
33
+ margin: 0,
34
+ marginBottom: theme.spacing(0.5),
35
+ color: "var(--pf-t--global--text--color--subtle) !important",
36
+ overflow: "hidden",
37
+ textOverflow: "ellipsis",
38
+ display: "-webkit-box",
39
+ WebkitLineClamp: 2,
40
+ WebkitBoxOrient: "vertical"
41
+ },
42
+ date: {
43
+ margin: 0,
44
+ color: "var(--pf-t--global--text--color--disabled) !important"
45
+ },
46
+ actions: {
47
+ flexShrink: 0
48
+ }
49
+ }));
50
+ const formatSavedDate = (isoDate) => {
51
+ const date = new Date(isoDate);
52
+ if (Number.isNaN(date.getTime())) {
53
+ return isoDate;
54
+ }
55
+ return date.toLocaleDateString(void 0, {
56
+ month: "numeric",
57
+ day: "numeric",
58
+ year: "numeric"
59
+ });
60
+ };
61
+ const SavedPromptCard = ({
62
+ prompt,
63
+ variant,
64
+ showDivider = false,
65
+ onApplyToInput,
66
+ onSendDirectly,
67
+ onDelete,
68
+ isSendDirectlyDisabled
69
+ }) => {
70
+ const { classes, cx } = useStyles();
71
+ return /* @__PURE__ */ jsx(
72
+ "div",
73
+ {
74
+ className: cx(classes.card, showDivider && classes.cardDivider),
75
+ "data-testid": `saved-prompt-card-${prompt.id}`,
76
+ "data-has-divider": showDivider ? "true" : "false",
77
+ children: /* @__PURE__ */ jsxs("div", { className: classes.row, children: [
78
+ /* @__PURE__ */ jsxs("div", { className: classes.content, children: [
79
+ /* @__PURE__ */ jsx(Tooltip, { content: prompt.name, children: /* @__PURE__ */ jsx("span", { className: classes.title, children: prompt.name }) }),
80
+ /* @__PURE__ */ jsx(Tooltip, { content: prompt.content, children: /* @__PURE__ */ jsx(Content, { component: ContentVariants.p, className: classes.body, children: prompt.content }) }),
81
+ /* @__PURE__ */ jsx(Content, { component: ContentVariants.small, className: classes.date, children: formatSavedDate(prompt.created_at) })
82
+ ] }),
83
+ /* @__PURE__ */ jsx("div", { className: classes.actions, children: /* @__PURE__ */ jsx(
84
+ SavedPromptKebabMenu,
85
+ {
86
+ prompt,
87
+ variant,
88
+ onApplyToInput,
89
+ onSendDirectly,
90
+ onDelete,
91
+ isSendDirectlyDisabled
92
+ }
93
+ ) })
94
+ ] })
95
+ }
96
+ );
97
+ };
98
+
99
+ export { SavedPromptCard };
100
+ //# sourceMappingURL=SavedPromptCard.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SavedPromptCard.esm.js","sources":["../../src/components/SavedPromptCard.tsx"],"sourcesContent":["/*\n * Copyright Red Hat, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { Content, ContentVariants, Tooltip } from '@patternfly/react-core';\nimport { makeStyles } from 'tss-react/mui';\n\nimport { SavedPrompt } from '@red-hat-developer-hub/backstage-plugin-intelligent-assistant-common';\n\nimport {\n SavedPromptKebabMenu,\n SavedPromptKebabVariant,\n} from './SavedPromptKebabMenu';\n\ntype SavedPromptCardProps = {\n prompt: SavedPrompt;\n variant: SavedPromptKebabVariant;\n showDivider?: boolean;\n onApplyToInput?: (content: string) => void;\n onSendDirectly: (content: string) => void;\n onDelete: (prompt: SavedPrompt) => void;\n isSendDirectlyDisabled?: boolean;\n};\n\nconst useStyles = makeStyles()(theme => ({\n card: {\n padding: `${theme.spacing(1.5)} 0`,\n },\n cardDivider: {\n borderBottom: '1px solid var(--pf-t--global--border--color--default)',\n },\n row: {\n display: 'flex',\n alignItems: 'flex-start',\n },\n content: {\n flex: '1 1 0%',\n minWidth: 0,\n },\n title: {\n display: 'block',\n minWidth: 0,\n maxWidth: '100%',\n margin: 0,\n marginBottom: theme.spacing(0.5),\n fontWeight: 600,\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n },\n body: {\n margin: 0,\n marginBottom: theme.spacing(0.5),\n color: 'var(--pf-t--global--text--color--subtle) !important',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n display: '-webkit-box',\n WebkitLineClamp: 2,\n WebkitBoxOrient: 'vertical',\n },\n date: {\n margin: 0,\n color: 'var(--pf-t--global--text--color--disabled) !important',\n },\n actions: {\n flexShrink: 0,\n },\n}));\n\nconst formatSavedDate = (isoDate: string): string => {\n const date = new Date(isoDate);\n if (Number.isNaN(date.getTime())) {\n return isoDate;\n }\n return date.toLocaleDateString(undefined, {\n month: 'numeric',\n day: 'numeric',\n year: 'numeric',\n });\n};\n\nexport const SavedPromptCard = ({\n prompt,\n variant,\n showDivider = false,\n onApplyToInput,\n onSendDirectly,\n onDelete,\n isSendDirectlyDisabled,\n}: SavedPromptCardProps) => {\n const { classes, cx } = useStyles();\n\n return (\n <div\n className={cx(classes.card, showDivider && classes.cardDivider)}\n data-testid={`saved-prompt-card-${prompt.id}`}\n data-has-divider={showDivider ? 'true' : 'false'}\n >\n <div className={classes.row}>\n <div className={classes.content}>\n <Tooltip content={prompt.name}>\n <span className={classes.title}>{prompt.name}</span>\n </Tooltip>\n <Tooltip content={prompt.content}>\n <Content component={ContentVariants.p} className={classes.body}>\n {prompt.content}\n </Content>\n </Tooltip>\n <Content component={ContentVariants.small} className={classes.date}>\n {formatSavedDate(prompt.created_at)}\n </Content>\n </div>\n <div className={classes.actions}>\n <SavedPromptKebabMenu\n prompt={prompt}\n variant={variant}\n onApplyToInput={onApplyToInput}\n onSendDirectly={onSendDirectly}\n onDelete={onDelete}\n isSendDirectlyDisabled={isSendDirectlyDisabled}\n />\n </div>\n </div>\n </div>\n );\n};\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,87 @@
1
+ import { jsx } from 'react/jsx-runtime';
2
+ import { useState } from 'react';
3
+ import { Dropdown, DropdownList, MenuToggle } from '@patternfly/react-core';
4
+ import { EllipsisHIcon } from '@patternfly/react-icons';
5
+ import { makeStyles } from 'tss-react/mui';
6
+ import { useTranslation } from '../hooks/useTranslation.esm.js';
7
+ import { SavedPromptMenuItems } from './SavedPromptMenuItems.esm.js';
8
+
9
+ const useStyles = makeStyles()(() => ({
10
+ menuButton: {
11
+ padding: 4
12
+ }
13
+ }));
14
+ const SavedPromptMenuToggle = ({
15
+ toggleRef,
16
+ promptName,
17
+ isOpen,
18
+ menuButtonClassName,
19
+ onToggle
20
+ }) => {
21
+ const { t } = useTranslation();
22
+ return /* @__PURE__ */ jsx(
23
+ MenuToggle,
24
+ {
25
+ ref: toggleRef,
26
+ variant: "plain",
27
+ className: menuButtonClassName,
28
+ "aria-label": t("savedPrompts.actions.menuAriaLabel", {
29
+ name: promptName
30
+ }),
31
+ isExpanded: isOpen,
32
+ onClick: onToggle,
33
+ children: /* @__PURE__ */ jsx(EllipsisHIcon, {})
34
+ }
35
+ );
36
+ };
37
+ const SavedPromptKebabMenu = ({
38
+ prompt,
39
+ variant,
40
+ onApplyToInput,
41
+ onSendDirectly,
42
+ onDelete,
43
+ isSendDirectlyDisabled = false
44
+ }) => {
45
+ const { classes } = useStyles();
46
+ const [isOpen, setIsOpen] = useState(false);
47
+ const closeMenu = () => setIsOpen(false);
48
+ return /* @__PURE__ */ jsx(
49
+ Dropdown,
50
+ {
51
+ isOpen,
52
+ popperProps: {
53
+ position: "end",
54
+ preventOverflow: true
55
+ },
56
+ onOpenChange: setIsOpen,
57
+ toggle: (toggleRef) => /* @__PURE__ */ jsx(
58
+ SavedPromptMenuToggle,
59
+ {
60
+ toggleRef,
61
+ promptName: prompt.name,
62
+ isOpen,
63
+ menuButtonClassName: classes.menuButton,
64
+ onToggle: (event) => {
65
+ event.stopPropagation();
66
+ setIsOpen((current) => !current);
67
+ }
68
+ }
69
+ ),
70
+ children: /* @__PURE__ */ jsx(DropdownList, { style: { paddingInlineStart: 0 }, children: /* @__PURE__ */ jsx(
71
+ SavedPromptMenuItems,
72
+ {
73
+ prompt,
74
+ variant,
75
+ onApplyToInput,
76
+ onSendDirectly,
77
+ onDelete,
78
+ isSendDirectlyDisabled,
79
+ closeMenu
80
+ }
81
+ ) })
82
+ }
83
+ );
84
+ };
85
+
86
+ export { SavedPromptKebabMenu };
87
+ //# sourceMappingURL=SavedPromptKebabMenu.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SavedPromptKebabMenu.esm.js","sources":["../../src/components/SavedPromptKebabMenu.tsx"],"sourcesContent":["/*\n * Copyright Red Hat, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { useState, type MouseEvent, type Ref } from 'react';\n\nimport {\n Dropdown,\n DropdownList,\n MenuToggle,\n type MenuToggleElement,\n} from '@patternfly/react-core';\nimport { EllipsisHIcon } from '@patternfly/react-icons';\nimport { makeStyles } from 'tss-react/mui';\n\nimport { SavedPrompt } from '@red-hat-developer-hub/backstage-plugin-intelligent-assistant-common';\n\nimport { useTranslation } from '../hooks/useTranslation';\nimport { SavedPromptMenuItems } from './SavedPromptMenuItems';\n\nexport type SavedPromptKebabVariant = 'settings' | 'sidebar';\n\ntype SavedPromptKebabMenuProps = {\n prompt: SavedPrompt;\n variant: SavedPromptKebabVariant;\n onApplyToInput?: (content: string) => void;\n onSendDirectly: (content: string) => void;\n onDelete: (prompt: SavedPrompt) => void;\n isSendDirectlyDisabled?: boolean;\n};\n\nconst useStyles = makeStyles()(() => ({\n menuButton: {\n padding: 4,\n },\n}));\n\ntype SavedPromptMenuToggleProps = {\n toggleRef: Ref<MenuToggleElement>;\n promptName: string;\n isOpen: boolean;\n menuButtonClassName: string;\n onToggle: (event: MouseEvent) => void;\n};\n\nconst SavedPromptMenuToggle = ({\n toggleRef,\n promptName,\n isOpen,\n menuButtonClassName,\n onToggle,\n}: SavedPromptMenuToggleProps) => {\n const { t } = useTranslation();\n\n return (\n <MenuToggle\n ref={toggleRef}\n variant=\"plain\"\n className={menuButtonClassName}\n aria-label={t('savedPrompts.actions.menuAriaLabel' as any, {\n name: promptName,\n })}\n isExpanded={isOpen}\n onClick={onToggle}\n >\n <EllipsisHIcon />\n </MenuToggle>\n );\n};\n\nexport const SavedPromptKebabMenu = ({\n prompt,\n variant,\n onApplyToInput,\n onSendDirectly,\n onDelete,\n isSendDirectlyDisabled = false,\n}: SavedPromptKebabMenuProps) => {\n const { classes } = useStyles();\n const [isOpen, setIsOpen] = useState(false);\n\n const closeMenu = () => setIsOpen(false);\n\n return (\n <Dropdown\n isOpen={isOpen}\n popperProps={{\n position: 'end',\n preventOverflow: true,\n }}\n onOpenChange={setIsOpen}\n toggle={toggleRef => (\n <SavedPromptMenuToggle\n toggleRef={toggleRef}\n promptName={prompt.name}\n isOpen={isOpen}\n menuButtonClassName={classes.menuButton}\n onToggle={event => {\n event.stopPropagation();\n setIsOpen(current => !current);\n }}\n />\n )}\n >\n <DropdownList style={{ paddingInlineStart: 0 }}>\n <SavedPromptMenuItems\n prompt={prompt}\n variant={variant}\n onApplyToInput={onApplyToInput}\n onSendDirectly={onSendDirectly}\n onDelete={onDelete}\n isSendDirectlyDisabled={isSendDirectlyDisabled}\n closeMenu={closeMenu}\n />\n </DropdownList>\n </Dropdown>\n );\n};\n"],"names":[],"mappings":";;;;;;;;AA0CA,MAAM,SAAA,GAAY,UAAA,EAAW,CAAE,OAAO;AAAA,EACpC,UAAA,EAAY;AAAA,IACV,OAAA,EAAS;AAAA;AAEb,CAAA,CAAE,CAAA;AAUF,MAAM,wBAAwB,CAAC;AAAA,EAC7B,SAAA;AAAA,EACA,UAAA;AAAA,EACA,MAAA;AAAA,EACA,mBAAA;AAAA,EACA;AACF,CAAA,KAAkC;AAChC,EAAA,MAAM,EAAE,CAAA,EAAE,GAAI,cAAA,EAAe;AAE7B,EAAA,uBACE,GAAA;AAAA,IAAC,UAAA;AAAA,IAAA;AAAA,MACC,GAAA,EAAK,SAAA;AAAA,MACL,OAAA,EAAQ,OAAA;AAAA,MACR,SAAA,EAAW,mBAAA;AAAA,MACX,YAAA,EAAY,EAAE,oCAAA,EAA6C;AAAA,QACzD,IAAA,EAAM;AAAA,OACP,CAAA;AAAA,MACD,UAAA,EAAY,MAAA;AAAA,MACZ,OAAA,EAAS,QAAA;AAAA,MAET,8BAAC,aAAA,EAAA,EAAc;AAAA;AAAA,GACjB;AAEJ,CAAA;AAEO,MAAM,uBAAuB,CAAC;AAAA,EACnC,MAAA;AAAA,EACA,OAAA;AAAA,EACA,cAAA;AAAA,EACA,cAAA;AAAA,EACA,QAAA;AAAA,EACA,sBAAA,GAAyB;AAC3B,CAAA,KAAiC;AAC/B,EAAA,MAAM,EAAE,OAAA,EAAQ,GAAI,SAAA,EAAU;AAC9B,EAAA,MAAM,CAAC,MAAA,EAAQ,SAAS,CAAA,GAAI,SAAS,KAAK,CAAA;AAE1C,EAAA,MAAM,SAAA,GAAY,MAAM,SAAA,CAAU,KAAK,CAAA;AAEvC,EAAA,uBACE,GAAA;AAAA,IAAC,QAAA;AAAA,IAAA;AAAA,MACC,MAAA;AAAA,MACA,WAAA,EAAa;AAAA,QACX,QAAA,EAAU,KAAA;AAAA,QACV,eAAA,EAAiB;AAAA,OACnB;AAAA,MACA,YAAA,EAAc,SAAA;AAAA,MACd,QAAQ,CAAA,SAAA,qBACN,GAAA;AAAA,QAAC,qBAAA;AAAA,QAAA;AAAA,UACC,SAAA;AAAA,UACA,YAAY,MAAA,CAAO,IAAA;AAAA,UACnB,MAAA;AAAA,UACA,qBAAqB,OAAA,CAAQ,UAAA;AAAA,UAC7B,UAAU,CAAA,KAAA,KAAS;AACjB,YAAA,KAAA,CAAM,eAAA,EAAgB;AACtB,YAAA,SAAA,CAAU,CAAA,OAAA,KAAW,CAAC,OAAO,CAAA;AAAA,UAC/B;AAAA;AAAA,OACF;AAAA,MAGF,8BAAC,YAAA,EAAA,EAAa,KAAA,EAAO,EAAE,kBAAA,EAAoB,GAAE,EAC3C,QAAA,kBAAA,GAAA;AAAA,QAAC,oBAAA;AAAA,QAAA;AAAA,UACC,MAAA;AAAA,UACA,OAAA;AAAA,UACA,cAAA;AAAA,UACA,cAAA;AAAA,UACA,QAAA;AAAA,UACA,sBAAA;AAAA,UACA;AAAA;AAAA,OACF,EACF;AAAA;AAAA,GACF;AAEJ;;;;"}
@@ -0,0 +1,52 @@
1
+ import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
2
+ import { DropdownItem } from '@patternfly/react-core';
3
+ import { ArrowRightIcon, PaperPlaneIcon, TrashIcon } from '@patternfly/react-icons';
4
+ import { useTranslation } from '../hooks/useTranslation.esm.js';
5
+
6
+ const SavedPromptMenuItems = ({
7
+ prompt,
8
+ variant,
9
+ onApplyToInput,
10
+ onSendDirectly,
11
+ onDelete,
12
+ isSendDirectlyDisabled = false,
13
+ closeMenu
14
+ }) => {
15
+ const { t } = useTranslation();
16
+ const handleAction = (action) => (event) => {
17
+ event.stopPropagation();
18
+ action();
19
+ closeMenu?.();
20
+ };
21
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
22
+ variant === "settings" && onApplyToInput && /* @__PURE__ */ jsx(
23
+ DropdownItem,
24
+ {
25
+ icon: /* @__PURE__ */ jsx(ArrowRightIcon, {}),
26
+ onClick: handleAction(() => onApplyToInput(prompt.content)),
27
+ children: t("savedPrompts.actions.apply")
28
+ }
29
+ ),
30
+ /* @__PURE__ */ jsx(
31
+ DropdownItem,
32
+ {
33
+ icon: /* @__PURE__ */ jsx(PaperPlaneIcon, {}),
34
+ isDisabled: isSendDirectlyDisabled,
35
+ description: isSendDirectlyDisabled ? t("savedPrompts.actions.sendDisabledStreaming") : void 0,
36
+ onClick: handleAction(() => onSendDirectly(prompt.content)),
37
+ children: t("savedPrompts.actions.send")
38
+ }
39
+ ),
40
+ /* @__PURE__ */ jsx(
41
+ DropdownItem,
42
+ {
43
+ icon: /* @__PURE__ */ jsx(TrashIcon, {}),
44
+ onClick: handleAction(() => onDelete(prompt)),
45
+ children: t("savedPrompts.actions.delete")
46
+ }
47
+ )
48
+ ] });
49
+ };
50
+
51
+ export { SavedPromptMenuItems };
52
+ //# sourceMappingURL=SavedPromptMenuItems.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SavedPromptMenuItems.esm.js","sources":["../../src/components/SavedPromptMenuItems.tsx"],"sourcesContent":["/*\n * Copyright Red Hat, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { MouseEvent } from 'react';\n\nimport { DropdownItem } from '@patternfly/react-core';\nimport {\n ArrowRightIcon,\n PaperPlaneIcon,\n TrashIcon,\n} from '@patternfly/react-icons';\n\nimport { SavedPrompt } from '@red-hat-developer-hub/backstage-plugin-intelligent-assistant-common';\n\nimport { useTranslation } from '../hooks/useTranslation';\nimport { SavedPromptKebabVariant } from './SavedPromptKebabMenu';\n\ntype SavedPromptMenuItemsProps = {\n prompt: SavedPrompt;\n variant: SavedPromptKebabVariant;\n onApplyToInput?: (content: string) => void;\n onSendDirectly: (content: string) => void;\n onDelete: (prompt: SavedPrompt) => void;\n isSendDirectlyDisabled?: boolean;\n closeMenu?: () => void;\n};\n\nexport const SavedPromptMenuItems = ({\n prompt,\n variant,\n onApplyToInput,\n onSendDirectly,\n onDelete,\n isSendDirectlyDisabled = false,\n closeMenu,\n}: SavedPromptMenuItemsProps) => {\n const { t } = useTranslation();\n\n const handleAction = (action: () => void) => (event: MouseEvent) => {\n event.stopPropagation();\n action();\n closeMenu?.();\n };\n\n return (\n <>\n {variant === 'settings' && onApplyToInput && (\n <DropdownItem\n icon={<ArrowRightIcon />}\n onClick={handleAction(() => onApplyToInput(prompt.content))}\n >\n {t('savedPrompts.actions.apply')}\n </DropdownItem>\n )}\n <DropdownItem\n icon={<PaperPlaneIcon />}\n isDisabled={isSendDirectlyDisabled}\n description={\n isSendDirectlyDisabled\n ? t('savedPrompts.actions.sendDisabledStreaming')\n : undefined\n }\n onClick={handleAction(() => onSendDirectly(prompt.content))}\n >\n {t('savedPrompts.actions.send')}\n </DropdownItem>\n <DropdownItem\n icon={<TrashIcon />}\n onClick={handleAction(() => onDelete(prompt))}\n >\n {t('savedPrompts.actions.delete')}\n </DropdownItem>\n </>\n );\n};\n"],"names":[],"mappings":";;;;;AAuCO,MAAM,uBAAuB,CAAC;AAAA,EACnC,MAAA;AAAA,EACA,OAAA;AAAA,EACA,cAAA;AAAA,EACA,cAAA;AAAA,EACA,QAAA;AAAA,EACA,sBAAA,GAAyB,KAAA;AAAA,EACzB;AACF,CAAA,KAAiC;AAC/B,EAAA,MAAM,EAAE,CAAA,EAAE,GAAI,cAAA,EAAe;AAE7B,EAAA,MAAM,YAAA,GAAe,CAAC,MAAA,KAAuB,CAAC,KAAA,KAAsB;AAClE,IAAA,KAAA,CAAM,eAAA,EAAgB;AACtB,IAAA,MAAA,EAAO;AACP,IAAA,SAAA,IAAY;AAAA,EACd,CAAA;AAEA,EAAA,uBACE,IAAA,CAAA,QAAA,EAAA,EACG,QAAA,EAAA;AAAA,IAAA,OAAA,KAAY,cAAc,cAAA,oBACzB,GAAA;AAAA,MAAC,YAAA;AAAA,MAAA;AAAA,QACC,IAAA,sBAAO,cAAA,EAAA,EAAe,CAAA;AAAA,QACtB,SAAS,YAAA,CAAa,MAAM,cAAA,CAAe,MAAA,CAAO,OAAO,CAAC,CAAA;AAAA,QAEzD,YAAE,4BAA4B;AAAA;AAAA,KACjC;AAAA,oBAEF,GAAA;AAAA,MAAC,YAAA;AAAA,MAAA;AAAA,QACC,IAAA,sBAAO,cAAA,EAAA,EAAe,CAAA;AAAA,QACtB,UAAA,EAAY,sBAAA;AAAA,QACZ,WAAA,EACE,sBAAA,GACI,CAAA,CAAE,4CAA4C,CAAA,GAC9C,MAAA;AAAA,QAEN,SAAS,YAAA,CAAa,MAAM,cAAA,CAAe,MAAA,CAAO,OAAO,CAAC,CAAA;AAAA,QAEzD,YAAE,2BAA2B;AAAA;AAAA,KAChC;AAAA,oBACA,GAAA;AAAA,MAAC,YAAA;AAAA,MAAA;AAAA,QACC,IAAA,sBAAO,SAAA,EAAA,EAAU,CAAA;AAAA,QACjB,OAAA,EAAS,YAAA,CAAa,MAAM,QAAA,CAAS,MAAM,CAAC,CAAA;AAAA,QAE3C,YAAE,6BAA6B;AAAA;AAAA;AAClC,GAAA,EACF,CAAA;AAEJ;;;;"}
@@ -0,0 +1,63 @@
1
+ import { jsx, jsxs } from 'react/jsx-runtime';
2
+ import { Content, ContentVariants, Button } from '@patternfly/react-core';
3
+ import { FileAltIcon } from '@patternfly/react-icons';
4
+ import { makeStyles } from 'tss-react/mui';
5
+ import { useTranslation } from '../hooks/useTranslation.esm.js';
6
+
7
+ const useStyles = makeStyles()((theme) => ({
8
+ root: {
9
+ flex: 1,
10
+ display: "flex",
11
+ flexDirection: "column",
12
+ alignItems: "center",
13
+ textAlign: "center",
14
+ padding: theme.spacing(3, 2)
15
+ },
16
+ inner: {
17
+ display: "flex",
18
+ flexDirection: "column",
19
+ alignItems: "center",
20
+ maxWidth: 420
21
+ },
22
+ icon: {
23
+ fontSize: 48,
24
+ color: "var(--pf-t--global--icon--color--subtle)",
25
+ marginBottom: theme.spacing(1.5)
26
+ },
27
+ title: {
28
+ margin: 0,
29
+ marginBottom: theme.spacing(1),
30
+ fontWeight: 600
31
+ },
32
+ description: {
33
+ margin: 0,
34
+ marginBottom: theme.spacing(3),
35
+ color: "var(--pf-t--global--text--color--subtle)"
36
+ },
37
+ action: {
38
+ borderRadius: 999
39
+ }
40
+ }));
41
+ const SavedPromptsEmptyState = ({
42
+ onNewPrompt
43
+ }) => {
44
+ const { classes } = useStyles();
45
+ const { t } = useTranslation();
46
+ return /* @__PURE__ */ jsx("div", { className: classes.root, "data-testid": "saved-prompts-empty-state", children: /* @__PURE__ */ jsxs("div", { className: classes.inner, children: [
47
+ /* @__PURE__ */ jsx(FileAltIcon, { className: classes.icon, "aria-hidden": true }),
48
+ /* @__PURE__ */ jsx(Content, { component: ContentVariants.p, className: classes.title, children: t("savedPrompts.count.zero") }),
49
+ /* @__PURE__ */ jsx(Content, { component: ContentVariants.p, className: classes.description, children: t("savedPrompts.empty.description") }),
50
+ /* @__PURE__ */ jsx(
51
+ Button,
52
+ {
53
+ variant: "secondary",
54
+ className: classes.action,
55
+ onClick: onNewPrompt,
56
+ children: t("savedPrompts.newPrompt")
57
+ }
58
+ )
59
+ ] }) });
60
+ };
61
+
62
+ export { SavedPromptsEmptyState };
63
+ //# sourceMappingURL=SavedPromptsEmptyState.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SavedPromptsEmptyState.esm.js","sources":["../../src/components/SavedPromptsEmptyState.tsx"],"sourcesContent":["/*\n * Copyright Red Hat, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { Button, Content, ContentVariants } from '@patternfly/react-core';\nimport { FileAltIcon } from '@patternfly/react-icons';\nimport { makeStyles } from 'tss-react/mui';\n\nimport { useTranslation } from '../hooks/useTranslation';\n\ntype SavedPromptsEmptyStateProps = {\n onNewPrompt: () => void;\n};\n\nconst useStyles = makeStyles()(theme => ({\n root: {\n flex: 1,\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n textAlign: 'center',\n padding: theme.spacing(3, 2),\n },\n inner: {\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n maxWidth: 420,\n },\n icon: {\n fontSize: 48,\n color: 'var(--pf-t--global--icon--color--subtle)',\n marginBottom: theme.spacing(1.5),\n },\n title: {\n margin: 0,\n marginBottom: theme.spacing(1),\n fontWeight: 600,\n },\n description: {\n margin: 0,\n marginBottom: theme.spacing(3),\n color: 'var(--pf-t--global--text--color--subtle)',\n },\n action: {\n borderRadius: 999,\n },\n}));\n\nexport const SavedPromptsEmptyState = ({\n onNewPrompt,\n}: SavedPromptsEmptyStateProps) => {\n const { classes } = useStyles();\n const { t } = useTranslation();\n\n return (\n <div className={classes.root} data-testid=\"saved-prompts-empty-state\">\n <div className={classes.inner}>\n <FileAltIcon className={classes.icon} aria-hidden />\n <Content component={ContentVariants.p} className={classes.title}>\n {t('savedPrompts.count.zero')}\n </Content>\n <Content component={ContentVariants.p} className={classes.description}>\n {t('savedPrompts.empty.description')}\n </Content>\n <Button\n variant=\"secondary\"\n className={classes.action}\n onClick={onNewPrompt}\n >\n {t('savedPrompts.newPrompt')}\n </Button>\n </div>\n </div>\n );\n};\n"],"names":[],"mappings":";;;;;;AAyBA,MAAM,SAAA,GAAY,UAAA,EAAW,CAAE,CAAA,KAAA,MAAU;AAAA,EACvC,IAAA,EAAM;AAAA,IACJ,IAAA,EAAM,CAAA;AAAA,IACN,OAAA,EAAS,MAAA;AAAA,IACT,aAAA,EAAe,QAAA;AAAA,IACf,UAAA,EAAY,QAAA;AAAA,IACZ,SAAA,EAAW,QAAA;AAAA,IACX,OAAA,EAAS,KAAA,CAAM,OAAA,CAAQ,CAAA,EAAG,CAAC;AAAA,GAC7B;AAAA,EACA,KAAA,EAAO;AAAA,IACL,OAAA,EAAS,MAAA;AAAA,IACT,aAAA,EAAe,QAAA;AAAA,IACf,UAAA,EAAY,QAAA;AAAA,IACZ,QAAA,EAAU;AAAA,GACZ;AAAA,EACA,IAAA,EAAM;AAAA,IACJ,QAAA,EAAU,EAAA;AAAA,IACV,KAAA,EAAO,0CAAA;AAAA,IACP,YAAA,EAAc,KAAA,CAAM,OAAA,CAAQ,GAAG;AAAA,GACjC;AAAA,EACA,KAAA,EAAO;AAAA,IACL,MAAA,EAAQ,CAAA;AAAA,IACR,YAAA,EAAc,KAAA,CAAM,OAAA,CAAQ,CAAC,CAAA;AAAA,IAC7B,UAAA,EAAY;AAAA,GACd;AAAA,EACA,WAAA,EAAa;AAAA,IACX,MAAA,EAAQ,CAAA;AAAA,IACR,YAAA,EAAc,KAAA,CAAM,OAAA,CAAQ,CAAC,CAAA;AAAA,IAC7B,KAAA,EAAO;AAAA,GACT;AAAA,EACA,MAAA,EAAQ;AAAA,IACN,YAAA,EAAc;AAAA;AAElB,CAAA,CAAE,CAAA;AAEK,MAAM,yBAAyB,CAAC;AAAA,EACrC;AACF,CAAA,KAAmC;AACjC,EAAA,MAAM,EAAE,OAAA,EAAQ,GAAI,SAAA,EAAU;AAC9B,EAAA,MAAM,EAAE,CAAA,EAAE,GAAI,cAAA,EAAe;AAE7B,EAAA,uBACE,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAW,OAAA,CAAQ,IAAA,EAAM,aAAA,EAAY,2BAAA,EACxC,QAAA,kBAAA,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAW,OAAA,CAAQ,KAAA,EACtB,QAAA,EAAA;AAAA,oBAAA,GAAA,CAAC,WAAA,EAAA,EAAY,SAAA,EAAW,OAAA,CAAQ,IAAA,EAAM,eAAW,IAAA,EAAC,CAAA;AAAA,oBAClD,GAAA,CAAC,OAAA,EAAA,EAAQ,SAAA,EAAW,eAAA,CAAgB,CAAA,EAAG,WAAW,OAAA,CAAQ,KAAA,EACvD,QAAA,EAAA,CAAA,CAAE,yBAAyB,CAAA,EAC9B,CAAA;AAAA,oBACA,GAAA,CAAC,OAAA,EAAA,EAAQ,SAAA,EAAW,eAAA,CAAgB,CAAA,EAAG,WAAW,OAAA,CAAQ,WAAA,EACvD,QAAA,EAAA,CAAA,CAAE,gCAAgC,CAAA,EACrC,CAAA;AAAA,oBACA,GAAA;AAAA,MAAC,MAAA;AAAA,MAAA;AAAA,QACC,OAAA,EAAQ,WAAA;AAAA,QACR,WAAW,OAAA,CAAQ,MAAA;AAAA,QACnB,OAAA,EAAS,WAAA;AAAA,QAER,YAAE,wBAAwB;AAAA;AAAA;AAC7B,GAAA,EACF,CAAA,EACF,CAAA;AAEJ;;;;"}
@@ -0,0 +1,63 @@
1
+ import { jsx } from 'react/jsx-runtime';
2
+ import { Spinner, Alert } from '@patternfly/react-core';
3
+ import { makeStyles } from 'tss-react/mui';
4
+ import { useTranslation } from '../hooks/useTranslation.esm.js';
5
+ import { SavedPromptCard } from './SavedPromptCard.esm.js';
6
+
7
+ const useStyles = makeStyles()((theme) => ({
8
+ root: {
9
+ display: "flex",
10
+ flexDirection: "column"
11
+ },
12
+ loading: {
13
+ display: "flex",
14
+ justifyContent: "center",
15
+ padding: theme.spacing(3)
16
+ }
17
+ }));
18
+ const SavedPromptsList = ({
19
+ prompts,
20
+ loading,
21
+ error,
22
+ variant = "settings",
23
+ onApplyToInput,
24
+ onSendDirectly,
25
+ onDelete,
26
+ isSendDirectlyDisabled
27
+ }) => {
28
+ const { classes } = useStyles();
29
+ const { t } = useTranslation();
30
+ if (loading) {
31
+ return /* @__PURE__ */ jsx("div", { className: classes.loading, "data-testid": "saved-prompts-list-loading", children: /* @__PURE__ */ jsx(Spinner, { size: "lg", "aria-label": t("common.loading") }) });
32
+ }
33
+ if (error) {
34
+ return /* @__PURE__ */ jsx(
35
+ Alert,
36
+ {
37
+ variant: "danger",
38
+ isInline: true,
39
+ title: error,
40
+ "data-testid": "saved-prompts-list-error"
41
+ }
42
+ );
43
+ }
44
+ if (prompts.length === 0) {
45
+ return null;
46
+ }
47
+ return /* @__PURE__ */ jsx("div", { className: classes.root, "data-testid": "saved-prompts-list", children: prompts.map((prompt, index) => /* @__PURE__ */ jsx(
48
+ SavedPromptCard,
49
+ {
50
+ prompt,
51
+ variant,
52
+ showDivider: index < prompts.length - 1,
53
+ onApplyToInput,
54
+ onSendDirectly,
55
+ onDelete,
56
+ isSendDirectlyDisabled
57
+ },
58
+ prompt.id
59
+ )) });
60
+ };
61
+
62
+ export { SavedPromptsList };
63
+ //# sourceMappingURL=SavedPromptsList.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SavedPromptsList.esm.js","sources":["../../src/components/SavedPromptsList.tsx"],"sourcesContent":["/*\n * Copyright Red Hat, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { Alert, Spinner } from '@patternfly/react-core';\nimport { makeStyles } from 'tss-react/mui';\n\nimport { SavedPrompt } from '@red-hat-developer-hub/backstage-plugin-intelligent-assistant-common';\n\nimport { useTranslation } from '../hooks/useTranslation';\nimport { SavedPromptCard } from './SavedPromptCard';\nimport { SavedPromptKebabVariant } from './SavedPromptKebabMenu';\n\ntype SavedPromptsListProps = {\n prompts: SavedPrompt[];\n loading: boolean;\n error: string | null;\n variant?: SavedPromptKebabVariant;\n onApplyToInput?: (content: string) => void;\n onSendDirectly: (content: string) => void;\n onDelete: (prompt: SavedPrompt) => void;\n isSendDirectlyDisabled?: boolean;\n};\n\nconst useStyles = makeStyles()(theme => ({\n root: {\n display: 'flex',\n flexDirection: 'column',\n },\n loading: {\n display: 'flex',\n justifyContent: 'center',\n padding: theme.spacing(3),\n },\n}));\n\nexport const SavedPromptsList = ({\n prompts,\n loading,\n error,\n variant = 'settings',\n onApplyToInput,\n onSendDirectly,\n onDelete,\n isSendDirectlyDisabled,\n}: SavedPromptsListProps) => {\n const { classes } = useStyles();\n const { t } = useTranslation();\n\n if (loading) {\n return (\n <div className={classes.loading} data-testid=\"saved-prompts-list-loading\">\n <Spinner size=\"lg\" aria-label={t('common.loading')} />\n </div>\n );\n }\n\n if (error) {\n return (\n <Alert\n variant=\"danger\"\n isInline\n title={error}\n data-testid=\"saved-prompts-list-error\"\n />\n );\n }\n\n if (prompts.length === 0) {\n return null;\n }\n\n return (\n <div className={classes.root} data-testid=\"saved-prompts-list\">\n {prompts.map((prompt, index) => (\n <SavedPromptCard\n key={prompt.id}\n prompt={prompt}\n variant={variant}\n showDivider={index < prompts.length - 1}\n onApplyToInput={onApplyToInput}\n onSendDirectly={onSendDirectly}\n onDelete={onDelete}\n isSendDirectlyDisabled={isSendDirectlyDisabled}\n />\n ))}\n </div>\n );\n};\n"],"names":[],"mappings":";;;;;;AAmCA,MAAM,SAAA,GAAY,UAAA,EAAW,CAAE,CAAA,KAAA,MAAU;AAAA,EACvC,IAAA,EAAM;AAAA,IACJ,OAAA,EAAS,MAAA;AAAA,IACT,aAAA,EAAe;AAAA,GACjB;AAAA,EACA,OAAA,EAAS;AAAA,IACP,OAAA,EAAS,MAAA;AAAA,IACT,cAAA,EAAgB,QAAA;AAAA,IAChB,OAAA,EAAS,KAAA,CAAM,OAAA,CAAQ,CAAC;AAAA;AAE5B,CAAA,CAAE,CAAA;AAEK,MAAM,mBAAmB,CAAC;AAAA,EAC/B,OAAA;AAAA,EACA,OAAA;AAAA,EACA,KAAA;AAAA,EACA,OAAA,GAAU,UAAA;AAAA,EACV,cAAA;AAAA,EACA,cAAA;AAAA,EACA,QAAA;AAAA,EACA;AACF,CAAA,KAA6B;AAC3B,EAAA,MAAM,EAAE,OAAA,EAAQ,GAAI,SAAA,EAAU;AAC9B,EAAA,MAAM,EAAE,CAAA,EAAE,GAAI,cAAA,EAAe;AAE7B,EAAA,IAAI,OAAA,EAAS;AACX,IAAA,uBACE,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAW,OAAA,CAAQ,SAAS,aAAA,EAAY,4BAAA,EAC3C,QAAA,kBAAA,GAAA,CAAC,OAAA,EAAA,EAAQ,MAAK,IAAA,EAAK,YAAA,EAAY,CAAA,CAAE,gBAAgB,GAAG,CAAA,EACtD,CAAA;AAAA,EAEJ;AAEA,EAAA,IAAI,KAAA,EAAO;AACT,IAAA,uBACE,GAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACC,OAAA,EAAQ,QAAA;AAAA,QACR,QAAA,EAAQ,IAAA;AAAA,QACR,KAAA,EAAO,KAAA;AAAA,QACP,aAAA,EAAY;AAAA;AAAA,KACd;AAAA,EAEJ;AAEA,EAAA,IAAI,OAAA,CAAQ,WAAW,CAAA,EAAG;AACxB,IAAA,OAAO,IAAA;AAAA,EACT;AAEA,EAAA,uBACE,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAW,OAAA,CAAQ,IAAA,EAAM,aAAA,EAAY,oBAAA,EACvC,QAAA,EAAA,OAAA,CAAQ,GAAA,CAAI,CAAC,MAAA,EAAQ,KAAA,qBACpB,GAAA;AAAA,IAAC,eAAA;AAAA,IAAA;AAAA,MAEC,MAAA;AAAA,MACA,OAAA;AAAA,MACA,WAAA,EAAa,KAAA,GAAQ,OAAA,CAAQ,MAAA,GAAS,CAAA;AAAA,MACtC,cAAA;AAAA,MACA,cAAA;AAAA,MACA,QAAA;AAAA,MACA;AAAA,KAAA;AAAA,IAPK,MAAA,CAAO;AAAA,GASf,CAAA,EACH,CAAA;AAEJ;;;;"}