@neo4j-ndl/react 4.3.3 → 4.3.4
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/lib/cjs/ai/prompt/Prompt.js +7 -5
- package/lib/cjs/ai/prompt/Prompt.js.map +1 -1
- package/lib/cjs/ai/prompt/stories/prompt-advanced.story.js +4 -6
- package/lib/cjs/ai/prompt/stories/prompt-advanced.story.js.map +1 -1
- package/lib/cjs/ai/prompt/stories/prompt-default.story.js +4 -6
- package/lib/cjs/ai/prompt/stories/prompt-default.story.js.map +1 -1
- package/lib/cjs/ai/response/stories/response-full-example.story.js +20 -22
- package/lib/cjs/ai/response/stories/response-full-example.story.js.map +1 -1
- package/lib/esm/ai/prompt/Prompt.js +7 -5
- package/lib/esm/ai/prompt/Prompt.js.map +1 -1
- package/lib/esm/ai/prompt/stories/prompt-advanced.story.js +4 -6
- package/lib/esm/ai/prompt/stories/prompt-advanced.story.js.map +1 -1
- package/lib/esm/ai/prompt/stories/prompt-default.story.js +4 -6
- package/lib/esm/ai/prompt/stories/prompt-default.story.js.map +1 -1
- package/lib/esm/ai/response/stories/response-full-example.story.js +20 -22
- package/lib/esm/ai/response/stories/response-full-example.story.js.map +1 -1
- package/lib/types/ai/prompt/Prompt.d.ts +3 -1
- package/lib/types/ai/prompt/Prompt.d.ts.map +1 -1
- package/lib/types/ai/prompt/stories/prompt-advanced.story.d.ts.map +1 -1
- package/lib/types/ai/prompt/stories/prompt-default.story.d.ts.map +1 -1
- package/lib/types/ai/response/stories/response-full-example.story.d.ts.map +1 -1
- package/package.json +3 -5
|
@@ -48,7 +48,7 @@ const react_2 = require("react");
|
|
|
48
48
|
* @alpha - Changes to this component may be breaking.
|
|
49
49
|
*/
|
|
50
50
|
const PromptComponent = (_a) => {
|
|
51
|
-
var { value, onChange, maxRows = 5, isRunningPrompt = false, onSubmitPrompt, isSubmitDisabled = false, topContent, bottomContent, disclaimer = 'All information should be verified.', className, style, htmlAttributes, ref, textareaProps } = _a, restProps = __rest(_a, ["value", "onChange", "maxRows", "isRunningPrompt", "onSubmitPrompt", "isSubmitDisabled", "topContent", "bottomContent", "disclaimer", "className", "style", "htmlAttributes", "ref", "textareaProps"]);
|
|
51
|
+
var { value, onChange, maxRows = 5, isRunningPrompt = false, onSubmitPrompt, onCancelPrompt, isSubmitDisabled = false, topContent, bottomContent, disclaimer = 'All information should be verified.', className, style, htmlAttributes, ref, textareaProps } = _a, restProps = __rest(_a, ["value", "onChange", "maxRows", "isRunningPrompt", "onSubmitPrompt", "onCancelPrompt", "isSubmitDisabled", "topContent", "bottomContent", "disclaimer", "className", "style", "htmlAttributes", "ref", "textareaProps"]);
|
|
52
52
|
const classes = (0, classnames_1.default)('ndl-ai-prompt', className);
|
|
53
53
|
const textareaRef = (0, react_2.useRef)(null);
|
|
54
54
|
const textareaAboveRef = (0, react_2.useRef)(null);
|
|
@@ -130,13 +130,15 @@ const PromptComponent = (_a) => {
|
|
|
130
130
|
!e.shiftKey &&
|
|
131
131
|
isSubmitDisabled !== true) {
|
|
132
132
|
e.preventDefault();
|
|
133
|
-
|
|
133
|
+
if (isRunningPrompt !== true) {
|
|
134
|
+
onSubmitPrompt === null || onSubmitPrompt === void 0 ? void 0 : onSubmitPrompt(e);
|
|
135
|
+
}
|
|
134
136
|
}
|
|
135
|
-
} }, textareaProps)), (0, jsx_runtime_1.jsxs)("div", { className: "ndl-ai-prompt-textarea-below", children: [Boolean(bottomContent) && ((0, jsx_runtime_1.jsx)("div", { className: "ndl-ai-prompt-textarea-below-leading", children: bottomContent })), (0, jsx_runtime_1.jsx)(SumbitPromptButton, { isDisabled: isSubmitDisabled, isRunningPrompt: isRunningPrompt,
|
|
137
|
+
} }, textareaProps)), (0, jsx_runtime_1.jsxs)("div", { className: "ndl-ai-prompt-textarea-below", children: [Boolean(bottomContent) && ((0, jsx_runtime_1.jsx)("div", { className: "ndl-ai-prompt-textarea-below-leading", children: bottomContent })), (0, jsx_runtime_1.jsx)(SumbitPromptButton, { isDisabled: isSubmitDisabled, isRunningPrompt: isRunningPrompt, onSubmit: onSubmitPrompt, onCancel: onCancelPrompt })] })] }) }), Boolean(disclaimer) && ((0, jsx_runtime_1.jsx)(react_1.Typography, { variant: "body-small", className: "ndl-ai-prompt-footer", children: disclaimer }))] })));
|
|
136
138
|
};
|
|
137
|
-
const SumbitPromptButton = ({
|
|
139
|
+
const SumbitPromptButton = ({ onSubmit, onCancel, isDisabled, isRunningPrompt, }) => {
|
|
138
140
|
const description = isRunningPrompt === true ? 'Cancel' : 'Send';
|
|
139
|
-
return ((0, jsx_runtime_1.jsxs)(react_1.CleanIconButton, { className: "ndl-ai-prompt-submit-button", description: description, size: "medium", onClick:
|
|
141
|
+
return ((0, jsx_runtime_1.jsxs)(react_1.CleanIconButton, { className: "ndl-ai-prompt-submit-button", description: description, size: "medium", onClick: isRunningPrompt === true ? onCancel : onSubmit, isDisabled: isDisabled, children: [(0, jsx_runtime_1.jsx)(icons_1.ArrowSmallUpIconOutline, { style: {
|
|
140
142
|
opacity: isRunningPrompt === true ? 0 : 1,
|
|
141
143
|
position: isRunningPrompt === true ? 'absolute' : 'relative',
|
|
142
144
|
transform: isRunningPrompt === true ? 'translateY(-8px)' : 'translateY(0)',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Prompt.js","sourceRoot":"","sources":["../../../../src/ai/prompt/Prompt.tsx"],"names":[],"mappings":"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","sourcesContent":["/**\n *\n * Copyright (c) \"Neo4j\"\n * Neo4j Sweden AB [http://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Neo4j is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program. If not, see <http://www.gnu.org/licenses/>.\n */\n\nimport {\n CleanIconButton,\n DropdownButton,\n Menu,\n Typography,\n} from '@neo4j-ndl/react';\nimport {\n ArrowSmallUpIconOutline,\n CheckIconOutline,\n StopCircleIconOutline,\n} from '@neo4j-ndl/react/icons';\nimport classNames from 'classnames';\nimport { useCallback, useEffect, useRef, useState } from 'react';\n\nimport type { CommonProps, HtmlAttributes } from '../../_common/types';\n\ntype PromptProps = {\n /** The prompt text */\n value?: React.ComponentPropsWithoutRef<'textarea'>['value'];\n /** Callback function called when the prompt text changes */\n onChange?: (e: React.ChangeEvent<HTMLTextAreaElement>) => void;\n /** Whether the submit button is disabled */\n isSubmitDisabled?: boolean;\n /** Maximum number of rows the textarea can expand to */\n maxRows?: number;\n /** Whether the submit button is \"running\". Shows a stop icon when true. */\n isRunningPrompt?: boolean;\n /** Callback function called when the submit button is clicked */\n onSubmitPrompt?: (\n e:\n | React.KeyboardEvent<HTMLTextAreaElement>\n | React.MouseEvent<HTMLButtonElement, MouseEvent>,\n ) => void;\n /** Content to display above the textarea */\n topContent?: React.ReactNode;\n /** Content to display below the textarea */\n bottomContent?: React.ReactNode;\n /** Disclaimer to display below the component */\n disclaimer?: React.ReactNode;\n /** Props for the textarea element */\n textareaProps?: HtmlAttributes<'textarea'>;\n};\n\n/**\n * The component is used to display the prompt input for an LLM.\n * It includes a textarea for the user to enter their prompt and a submit button.\n * It can also display content above and below the textarea, like uploaded files or a select for changing agents.\n *\n * @alpha - Changes to this component may be breaking.\n */\nconst PromptComponent = ({\n value,\n onChange,\n maxRows = 5,\n isRunningPrompt = false,\n onSubmitPrompt,\n isSubmitDisabled = false,\n topContent,\n bottomContent,\n disclaimer = 'All information should be verified.',\n className,\n style,\n htmlAttributes,\n ref,\n textareaProps,\n ...restProps\n}: CommonProps<'div', PromptProps>) => {\n const classes = classNames('ndl-ai-prompt', className);\n\n const textareaRef = useRef<HTMLTextAreaElement>(null);\n const textareaAboveRef = useRef<HTMLDivElement>(null);\n const [lineHeight, setLineHeight] = useState(0);\n\n /** File overflow stuff */\n useEffect(() => {\n let rafId: number | null = null;\n\n const checkOverflow = () => {\n if (textareaAboveRef.current !== null) {\n const element = textareaAboveRef.current;\n const maxHeight = parseFloat(\n getComputedStyle(element).maxHeight.replace('px', ''),\n );\n const scrollHeight = element.scrollHeight;\n\n if (scrollHeight > maxHeight) {\n element.classList.add('ndl-can-scroll');\n } else {\n element.classList.remove('ndl-can-scroll');\n }\n }\n };\n\n const debouncedCheck = () => {\n if (rafId !== null) {\n cancelAnimationFrame(rafId);\n }\n rafId = requestAnimationFrame(checkOverflow);\n };\n\n // Initial check\n checkOverflow();\n\n const resizeObserver = new ResizeObserver(debouncedCheck);\n const mutationObserver = new MutationObserver(debouncedCheck);\n\n if (textareaAboveRef.current !== null) {\n resizeObserver.observe(textareaAboveRef.current);\n mutationObserver.observe(textareaAboveRef.current, {\n childList: true,\n subtree: true,\n });\n }\n\n return () => {\n if (rafId !== null) {\n cancelAnimationFrame(rafId);\n }\n resizeObserver.disconnect();\n mutationObserver.disconnect();\n };\n }, []);\n\n /** Textarea stuff */\n useEffect(() => {\n if (textareaRef.current !== null) {\n const computed = window.getComputedStyle(textareaRef.current);\n setLineHeight(parseInt(computed.lineHeight));\n }\n }, []);\n\n const adjustTextareaHeight = useCallback(() => {\n const ta = textareaRef.current;\n\n if (ta !== null && lineHeight > 0) {\n // Reset height so scrollHeight measures correctly\n ta.style.height = 'auto';\n\n const maxHeight = lineHeight * maxRows;\n\n if (ta.scrollHeight <= maxHeight) {\n ta.style.overflowY = 'hidden';\n ta.style.height = `${ta.scrollHeight}px`;\n } else {\n ta.style.overflowY = 'auto';\n ta.style.height = `${maxHeight}px`;\n }\n }\n }, [lineHeight, maxRows]);\n\n // Adjust height when prompt value changes (including when cleared)\n useEffect(() => {\n adjustTextareaHeight();\n }, [value, adjustTextareaHeight]);\n\n const handleInput = (e: React.ChangeEvent<HTMLTextAreaElement>) => {\n adjustTextareaHeight();\n onChange?.(e);\n };\n\n return (\n <div\n ref={ref}\n className={classes}\n style={style}\n {...restProps}\n {...htmlAttributes}\n >\n <div className=\"ndl-ai-prompt-wrapper\">\n <div className=\"ndl-ai-prompt-wrapper-inner\">\n {Boolean(topContent) && (\n <div\n className=\"ndl-ai-prompt-textarea-above\"\n ref={textareaAboveRef}\n >\n {topContent}\n </div>\n )}\n <textarea\n placeholder=\"Ask anything\"\n className=\"ndl-ai-prompt-textarea\"\n rows={1}\n onChange={handleInput}\n value={value}\n ref={textareaRef}\n onKeyDown={(e) => {\n if (\n e.key === 'Enter' &&\n !e.shiftKey &&\n isSubmitDisabled !== true\n ) {\n e.preventDefault();\n onSubmitPrompt?.(e);\n }\n }}\n {...textareaProps}\n />\n <div className=\"ndl-ai-prompt-textarea-below\">\n {Boolean(bottomContent) && (\n <div className=\"ndl-ai-prompt-textarea-below-leading\">\n {bottomContent}\n </div>\n )}\n <SumbitPromptButton\n isDisabled={isSubmitDisabled}\n isRunningPrompt={isRunningPrompt}\n onClick={onSubmitPrompt}\n />\n </div>\n </div>\n </div>\n {Boolean(disclaimer) && (\n <Typography variant=\"body-small\" className=\"ndl-ai-prompt-footer\">\n {disclaimer}\n </Typography>\n )}\n </div>\n );\n};\n\nconst SumbitPromptButton = ({\n onClick,\n isDisabled,\n isRunningPrompt,\n}: {\n isDisabled?: boolean;\n isRunningPrompt?: boolean;\n onClick?: (e: React.MouseEvent<HTMLButtonElement, MouseEvent>) => void;\n}) => {\n const description = isRunningPrompt === true ? 'Cancel' : 'Send';\n\n return (\n <CleanIconButton\n className=\"ndl-ai-prompt-submit-button\"\n description={description}\n size=\"medium\"\n onClick={onClick}\n isDisabled={isDisabled}\n >\n <ArrowSmallUpIconOutline\n style={{\n opacity: isRunningPrompt === true ? 0 : 1,\n position: isRunningPrompt === true ? 'absolute' : 'relative',\n transform:\n isRunningPrompt === true ? 'translateY(-8px)' : 'translateY(0)',\n }}\n />\n <StopCircleIconOutline\n style={{\n opacity: isRunningPrompt === true ? 1 : 0,\n position: isRunningPrompt === true ? 'relative' : 'absolute',\n }}\n />\n </CleanIconButton>\n );\n};\n\ntype AgentSelectProps = {\n value: { label: React.ReactNode; value: string };\n options: Array<{ label: React.ReactNode; value: string }>;\n onChange: (option: { label: React.ReactNode; value: string }) => void;\n};\n\nconst AgentSelect = ({ value, options = [], onChange }: AgentSelectProps) => {\n const anchorRef = useRef<HTMLButtonElement>(null);\n const [isMenuOpen, setIsMenuOpen] = useState(false);\n\n const displayLabel = value?.label ?? options[0]?.label ?? '';\n\n const handleItemClick = (option: {\n label: React.ReactNode;\n value: string;\n }) => {\n onChange?.(option);\n setIsMenuOpen(false);\n };\n\n return (\n <>\n <DropdownButton\n size=\"small\"\n className=\"ndl-ai-prompt-dropdown-button\"\n onClick={() => setIsMenuOpen((old) => !old)}\n isOpen={isMenuOpen}\n ref={anchorRef}\n >\n {displayLabel}\n </DropdownButton>\n <Menu\n isOpen={isMenuOpen}\n onClose={() => setIsMenuOpen(false)}\n anchorRef={anchorRef}\n placement=\"top-start-bottom-start\"\n >\n <Menu.Items>\n {options.map((option) => (\n <Menu.Item\n key={option.value}\n title={option.label}\n onClick={() => handleItemClick(option)}\n leadingVisual={\n value?.value === option.value ? <CheckIconOutline /> : null\n }\n />\n ))}\n </Menu.Items>\n </Menu>\n </>\n );\n};\n\nconst Prompt = Object.assign(PromptComponent, {\n Select: AgentSelect,\n});\n\nexport { Prompt };\n"]}
|
|
1
|
+
{"version":3,"file":"Prompt.js","sourceRoot":"","sources":["../../../../src/ai/prompt/Prompt.tsx"],"names":[],"mappings":"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","sourcesContent":["/**\n *\n * Copyright (c) \"Neo4j\"\n * Neo4j Sweden AB [http://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Neo4j is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program. If not, see <http://www.gnu.org/licenses/>.\n */\n\nimport {\n CleanIconButton,\n DropdownButton,\n Menu,\n Typography,\n} from '@neo4j-ndl/react';\nimport {\n ArrowSmallUpIconOutline,\n CheckIconOutline,\n StopCircleIconOutline,\n} from '@neo4j-ndl/react/icons';\nimport classNames from 'classnames';\nimport { useCallback, useEffect, useRef, useState } from 'react';\n\nimport type { CommonProps, HtmlAttributes } from '../../_common/types';\n\ntype PromptProps = {\n /** The prompt text */\n value?: React.ComponentPropsWithoutRef<'textarea'>['value'];\n /** Callback function called when the prompt text changes */\n onChange?: (e: React.ChangeEvent<HTMLTextAreaElement>) => void;\n /** Whether the submit button is disabled */\n isSubmitDisabled?: boolean;\n /** Maximum number of rows the textarea can expand to */\n maxRows?: number;\n /** Whether the submit button is \"running\". Shows a stop icon when true. */\n isRunningPrompt?: boolean;\n /** Callback function called when the submit button is clicked */\n onSubmitPrompt?: (\n e:\n | React.KeyboardEvent<HTMLTextAreaElement>\n | React.MouseEvent<HTMLButtonElement, MouseEvent>,\n ) => void;\n /** Callback function called when the cancel button is clicked */\n onCancelPrompt?: (e: React.MouseEvent<HTMLButtonElement, MouseEvent>) => void;\n /** Content to display above the textarea */\n topContent?: React.ReactNode;\n /** Content to display below the textarea */\n bottomContent?: React.ReactNode;\n /** Disclaimer to display below the component */\n disclaimer?: React.ReactNode;\n /** Props for the textarea element */\n textareaProps?: HtmlAttributes<'textarea'>;\n};\n\n/**\n * The component is used to display the prompt input for an LLM.\n * It includes a textarea for the user to enter their prompt and a submit button.\n * It can also display content above and below the textarea, like uploaded files or a select for changing agents.\n *\n * @alpha - Changes to this component may be breaking.\n */\nconst PromptComponent = ({\n value,\n onChange,\n maxRows = 5,\n isRunningPrompt = false,\n onSubmitPrompt,\n onCancelPrompt,\n isSubmitDisabled = false,\n topContent,\n bottomContent,\n disclaimer = 'All information should be verified.',\n className,\n style,\n htmlAttributes,\n ref,\n textareaProps,\n ...restProps\n}: CommonProps<'div', PromptProps>) => {\n const classes = classNames('ndl-ai-prompt', className);\n\n const textareaRef = useRef<HTMLTextAreaElement>(null);\n const textareaAboveRef = useRef<HTMLDivElement>(null);\n const [lineHeight, setLineHeight] = useState(0);\n\n /** File overflow stuff */\n useEffect(() => {\n let rafId: number | null = null;\n\n const checkOverflow = () => {\n if (textareaAboveRef.current !== null) {\n const element = textareaAboveRef.current;\n const maxHeight = parseFloat(\n getComputedStyle(element).maxHeight.replace('px', ''),\n );\n const scrollHeight = element.scrollHeight;\n\n if (scrollHeight > maxHeight) {\n element.classList.add('ndl-can-scroll');\n } else {\n element.classList.remove('ndl-can-scroll');\n }\n }\n };\n\n const debouncedCheck = () => {\n if (rafId !== null) {\n cancelAnimationFrame(rafId);\n }\n rafId = requestAnimationFrame(checkOverflow);\n };\n\n // Initial check\n checkOverflow();\n\n const resizeObserver = new ResizeObserver(debouncedCheck);\n const mutationObserver = new MutationObserver(debouncedCheck);\n\n if (textareaAboveRef.current !== null) {\n resizeObserver.observe(textareaAboveRef.current);\n mutationObserver.observe(textareaAboveRef.current, {\n childList: true,\n subtree: true,\n });\n }\n\n return () => {\n if (rafId !== null) {\n cancelAnimationFrame(rafId);\n }\n resizeObserver.disconnect();\n mutationObserver.disconnect();\n };\n }, []);\n\n /** Textarea stuff */\n useEffect(() => {\n if (textareaRef.current !== null) {\n const computed = window.getComputedStyle(textareaRef.current);\n setLineHeight(parseInt(computed.lineHeight));\n }\n }, []);\n\n const adjustTextareaHeight = useCallback(() => {\n const ta = textareaRef.current;\n\n if (ta !== null && lineHeight > 0) {\n // Reset height so scrollHeight measures correctly\n ta.style.height = 'auto';\n\n const maxHeight = lineHeight * maxRows;\n\n if (ta.scrollHeight <= maxHeight) {\n ta.style.overflowY = 'hidden';\n ta.style.height = `${ta.scrollHeight}px`;\n } else {\n ta.style.overflowY = 'auto';\n ta.style.height = `${maxHeight}px`;\n }\n }\n }, [lineHeight, maxRows]);\n\n // Adjust height when prompt value changes (including when cleared)\n useEffect(() => {\n adjustTextareaHeight();\n }, [value, adjustTextareaHeight]);\n\n const handleInput = (e: React.ChangeEvent<HTMLTextAreaElement>) => {\n adjustTextareaHeight();\n onChange?.(e);\n };\n\n return (\n <div\n ref={ref}\n className={classes}\n style={style}\n {...restProps}\n {...htmlAttributes}\n >\n <div className=\"ndl-ai-prompt-wrapper\">\n <div className=\"ndl-ai-prompt-wrapper-inner\">\n {Boolean(topContent) && (\n <div\n className=\"ndl-ai-prompt-textarea-above\"\n ref={textareaAboveRef}\n >\n {topContent}\n </div>\n )}\n <textarea\n placeholder=\"Ask anything\"\n className=\"ndl-ai-prompt-textarea\"\n rows={1}\n onChange={handleInput}\n value={value}\n ref={textareaRef}\n onKeyDown={(e) => {\n if (\n e.key === 'Enter' &&\n !e.shiftKey &&\n isSubmitDisabled !== true\n ) {\n e.preventDefault();\n\n if (isRunningPrompt !== true) {\n onSubmitPrompt?.(e);\n }\n }\n }}\n {...textareaProps}\n />\n <div className=\"ndl-ai-prompt-textarea-below\">\n {Boolean(bottomContent) && (\n <div className=\"ndl-ai-prompt-textarea-below-leading\">\n {bottomContent}\n </div>\n )}\n <SumbitPromptButton\n isDisabled={isSubmitDisabled}\n isRunningPrompt={isRunningPrompt}\n onSubmit={onSubmitPrompt}\n onCancel={onCancelPrompt}\n />\n </div>\n </div>\n </div>\n {Boolean(disclaimer) && (\n <Typography variant=\"body-small\" className=\"ndl-ai-prompt-footer\">\n {disclaimer}\n </Typography>\n )}\n </div>\n );\n};\n\nconst SumbitPromptButton = ({\n onSubmit,\n onCancel,\n isDisabled,\n isRunningPrompt,\n}: {\n isDisabled?: boolean;\n isRunningPrompt?: boolean;\n onSubmit?: (e: React.MouseEvent<HTMLButtonElement, MouseEvent>) => void;\n onCancel?: (e: React.MouseEvent<HTMLButtonElement, MouseEvent>) => void;\n}) => {\n const description = isRunningPrompt === true ? 'Cancel' : 'Send';\n\n return (\n <CleanIconButton\n className=\"ndl-ai-prompt-submit-button\"\n description={description}\n size=\"medium\"\n onClick={isRunningPrompt === true ? onCancel : onSubmit}\n isDisabled={isDisabled}\n >\n <ArrowSmallUpIconOutline\n style={{\n opacity: isRunningPrompt === true ? 0 : 1,\n position: isRunningPrompt === true ? 'absolute' : 'relative',\n transform:\n isRunningPrompt === true ? 'translateY(-8px)' : 'translateY(0)',\n }}\n />\n <StopCircleIconOutline\n style={{\n opacity: isRunningPrompt === true ? 1 : 0,\n position: isRunningPrompt === true ? 'relative' : 'absolute',\n }}\n />\n </CleanIconButton>\n );\n};\n\ntype AgentSelectProps = {\n value: { label: React.ReactNode; value: string };\n options: Array<{ label: React.ReactNode; value: string }>;\n onChange: (option: { label: React.ReactNode; value: string }) => void;\n};\n\nconst AgentSelect = ({ value, options = [], onChange }: AgentSelectProps) => {\n const anchorRef = useRef<HTMLButtonElement>(null);\n const [isMenuOpen, setIsMenuOpen] = useState(false);\n\n const displayLabel = value?.label ?? options[0]?.label ?? '';\n\n const handleItemClick = (option: {\n label: React.ReactNode;\n value: string;\n }) => {\n onChange?.(option);\n setIsMenuOpen(false);\n };\n\n return (\n <>\n <DropdownButton\n size=\"small\"\n className=\"ndl-ai-prompt-dropdown-button\"\n onClick={() => setIsMenuOpen((old) => !old)}\n isOpen={isMenuOpen}\n ref={anchorRef}\n >\n {displayLabel}\n </DropdownButton>\n <Menu\n isOpen={isMenuOpen}\n onClose={() => setIsMenuOpen(false)}\n anchorRef={anchorRef}\n placement=\"top-start-bottom-start\"\n >\n <Menu.Items>\n {options.map((option) => (\n <Menu.Item\n key={option.value}\n title={option.label}\n onClick={() => handleItemClick(option)}\n leadingVisual={\n value?.value === option.value ? <CheckIconOutline /> : null\n }\n />\n ))}\n </Menu.Items>\n </Menu>\n </>\n );\n};\n\nconst Prompt = Object.assign(PromptComponent, {\n Select: AgentSelect,\n});\n\nexport { Prompt };\n"]}
|
|
@@ -36,13 +36,11 @@ const Component = () => {
|
|
|
36
36
|
const [selectedOption, setSelectedOption] = (0, react_2.useState)(options[0]);
|
|
37
37
|
const [prompt, setPrompt] = (0, react_2.useState)('');
|
|
38
38
|
const handleSubmitPrompt = () => {
|
|
39
|
-
setIsRunningPrompt(
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
setPrompt('');
|
|
43
|
-
}
|
|
39
|
+
setIsRunningPrompt(true);
|
|
40
|
+
alert(`You submitted the following prompt: ${prompt}`);
|
|
41
|
+
setPrompt('');
|
|
44
42
|
};
|
|
45
|
-
return ((0, jsx_runtime_1.jsx)(ai_1.Prompt, { isRunningPrompt: isRunningPrompt, value: prompt, onChange: (e) => setPrompt(e.target.value), onSubmitPrompt: handleSubmitPrompt, topContent: (0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(ai_1.FileTag, { isLoading: true, icon: (0, jsx_runtime_1.jsx)(icons_1.DocumentIconOutline, {}), fileName: "Science Fiction Bestsellers", fileType: "pdf", isRemovable: true, onClick: () => {
|
|
43
|
+
return ((0, jsx_runtime_1.jsx)(ai_1.Prompt, { isRunningPrompt: isRunningPrompt, value: prompt, onChange: (e) => setPrompt(e.target.value), onSubmitPrompt: handleSubmitPrompt, onCancelPrompt: () => setIsRunningPrompt(false), topContent: (0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(ai_1.FileTag, { isLoading: true, icon: (0, jsx_runtime_1.jsx)(icons_1.DocumentIconOutline, {}), fileName: "Science Fiction Bestsellers", fileType: "pdf", isRemovable: true, onClick: () => {
|
|
46
44
|
console.info('remove file');
|
|
47
45
|
} }), (0, jsx_runtime_1.jsx)(ai_1.ImageTag, { isLoading: true, src: "https://plus.unsplash.com/premium_photo-1676496046182-356a6a0ed002?q=80&w=2952&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D", alt: "Landscape image", fileName: "Landscape image", fileType: "jpg", isRemovable: true, onClick: () => {
|
|
48
46
|
console.info('remove image');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prompt-advanced.story.js","sourceRoot":"","sources":["../../../../../src/ai/prompt/stories/prompt-advanced.story.tsx"],"names":[],"mappings":";;;AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,mDAAiD;AAEjD,4CAAmD;AACnD,4CAAgE;AAChE,kDAA8E;AAC9E,iCAAiC;AAEjC,MAAM,SAAS,GAAG,GAAG,EAAE;IACrB,MAAM,CAAC,eAAe,EAAE,kBAAkB,CAAC,GAAG,IAAA,gBAAQ,EAAC,KAAK,CAAC,CAAC;IAC9D,MAAM,OAAO,GAAqD;QAChE,EAAE,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,OAAO,EAAE;QACrC,EAAE,KAAK,EAAE,eAAe,EAAE,KAAK,EAAE,eAAe,EAAE;QAClD,EAAE,KAAK,EAAE,eAAe,EAAE,KAAK,EAAE,eAAe,EAAE;KACnD,CAAC;IACF,MAAM,CAAC,cAAc,EAAE,iBAAiB,CAAC,GAAG,IAAA,gBAAQ,EAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;IACjE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,IAAA,gBAAQ,EAAC,EAAE,CAAC,CAAC;IAEzC,MAAM,kBAAkB,GAAG,GAAG,EAAE;QAC9B,kBAAkB,CAAC,
|
|
1
|
+
{"version":3,"file":"prompt-advanced.story.js","sourceRoot":"","sources":["../../../../../src/ai/prompt/stories/prompt-advanced.story.tsx"],"names":[],"mappings":"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","sourcesContent":["/**\n *\n * Copyright (c) \"Neo4j\"\n * Neo4j Sweden AB [http://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Neo4j is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program. If not, see <http://www.gnu.org/licenses/>.\n */\n\nimport '@neo4j-ndl/base/lib/neo4j-ds-styles.css';\n\nimport { CleanIconButton } from '@neo4j-ndl/react';\nimport { FileTag, ImageTag, Prompt } from '@neo4j-ndl/react/ai';\nimport { DocumentIconOutline, PlusIconOutline } from '@neo4j-ndl/react/icons';\nimport { useState } from 'react';\n\nconst Component = () => {\n const [isRunningPrompt, setIsRunningPrompt] = useState(false);\n const options: Array<{ label: React.ReactNode; value: string }> = [\n { label: 'Neo4j AI', value: 'neo4j' },\n { label: 'Special Agent', value: 'special-agent' },\n { label: 'Another Agent', value: 'another-agent' },\n ];\n const [selectedOption, setSelectedOption] = useState(options[0]);\n const [prompt, setPrompt] = useState('');\n\n const handleSubmitPrompt = () => {\n setIsRunningPrompt(true);\n alert(`You submitted the following prompt: ${prompt}`);\n setPrompt('');\n };\n\n return (\n <Prompt\n isRunningPrompt={isRunningPrompt}\n value={prompt}\n onChange={(e) => setPrompt(e.target.value)}\n onSubmitPrompt={handleSubmitPrompt}\n onCancelPrompt={() => setIsRunningPrompt(false)}\n topContent={\n <>\n <FileTag\n isLoading={true}\n icon={<DocumentIconOutline />}\n fileName=\"Science Fiction Bestsellers\"\n fileType=\"pdf\"\n isRemovable={true}\n onClick={() => {\n console.info('remove file');\n }}\n />\n <ImageTag\n isLoading={true}\n src=\"https://plus.unsplash.com/premium_photo-1676496046182-356a6a0ed002?q=80&w=2952&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D\"\n alt=\"Landscape image\"\n fileName=\"Landscape image\"\n fileType=\"jpg\"\n isRemovable={true}\n onClick={() => {\n console.info('remove image');\n }}\n />\n <FileTag\n icon={<DocumentIconOutline />}\n fileName=\"Science Fiction Bestsellers\"\n fileType=\"pdf\"\n isRemovable={true}\n onClick={() => {\n console.info('remove file');\n }}\n />\n <ImageTag\n src=\"https://plus.unsplash.com/premium_photo-1676496046182-356a6a0ed002?q=80&w=2952&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D\"\n alt=\"Landscape image\"\n fileName=\"Landscape image\"\n fileType=\"jpg\"\n isRemovable={true}\n onClick={() => {\n console.info('remove image');\n }}\n />\n </>\n }\n bottomContent={\n <>\n <Prompt.Select\n value={selectedOption}\n options={options}\n onChange={setSelectedOption}\n />\n <CleanIconButton description=\"Add stuff\" size=\"small\">\n <PlusIconOutline />\n </CleanIconButton>\n </>\n }\n />\n );\n};\n\nexport default Component;\n"]}
|
|
@@ -28,13 +28,11 @@ const Component = () => {
|
|
|
28
28
|
const [prompt, setPrompt] = (0, react_1.useState)('');
|
|
29
29
|
const [isRunningPrompt, setIsRunningPrompt] = (0, react_1.useState)(false);
|
|
30
30
|
const handleSubmitPrompt = () => {
|
|
31
|
-
setIsRunningPrompt(
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
setPrompt('');
|
|
35
|
-
}
|
|
31
|
+
setIsRunningPrompt(true);
|
|
32
|
+
alert(`You submitted the following prompt: ${prompt}`);
|
|
33
|
+
setPrompt('');
|
|
36
34
|
};
|
|
37
|
-
return ((0, jsx_runtime_1.jsx)(ai_1.Prompt, { isRunningPrompt: isRunningPrompt, value: prompt, onChange: (e) => setPrompt(e.target.value), onSubmitPrompt: handleSubmitPrompt }));
|
|
35
|
+
return ((0, jsx_runtime_1.jsx)(ai_1.Prompt, { isRunningPrompt: isRunningPrompt, value: prompt, onChange: (e) => setPrompt(e.target.value), onSubmitPrompt: handleSubmitPrompt, onCancelPrompt: () => setIsRunningPrompt(false) }));
|
|
38
36
|
};
|
|
39
37
|
exports.default = Component;
|
|
40
38
|
//# sourceMappingURL=prompt-default.story.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prompt-default.story.js","sourceRoot":"","sources":["../../../../../src/ai/prompt/stories/prompt-default.story.tsx"],"names":[],"mappings":";;;AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,mDAAiD;AAEjD,4CAA6C;AAC7C,iCAAiC;AAEjC,MAAM,SAAS,GAAG,GAAG,EAAE;IACrB,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,IAAA,gBAAQ,EAAC,EAAE,CAAC,CAAC;IACzC,MAAM,CAAC,eAAe,EAAE,kBAAkB,CAAC,GAAG,IAAA,gBAAQ,EAAC,KAAK,CAAC,CAAC;IAE9D,MAAM,kBAAkB,GAAG,GAAG,EAAE;QAC9B,kBAAkB,CAAC,
|
|
1
|
+
{"version":3,"file":"prompt-default.story.js","sourceRoot":"","sources":["../../../../../src/ai/prompt/stories/prompt-default.story.tsx"],"names":[],"mappings":";;;AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,mDAAiD;AAEjD,4CAA6C;AAC7C,iCAAiC;AAEjC,MAAM,SAAS,GAAG,GAAG,EAAE;IACrB,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,IAAA,gBAAQ,EAAC,EAAE,CAAC,CAAC;IACzC,MAAM,CAAC,eAAe,EAAE,kBAAkB,CAAC,GAAG,IAAA,gBAAQ,EAAC,KAAK,CAAC,CAAC;IAE9D,MAAM,kBAAkB,GAAG,GAAG,EAAE;QAC9B,kBAAkB,CAAC,IAAI,CAAC,CAAC;QACzB,KAAK,CAAC,uCAAuC,MAAM,EAAE,CAAC,CAAC;QACvD,SAAS,CAAC,EAAE,CAAC,CAAC;IAChB,CAAC,CAAC;IAEF,OAAO,CACL,uBAAC,WAAM,IACL,eAAe,EAAE,eAAe,EAChC,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,CAAC,CAAyC,EAAE,EAAE,CACtD,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAE3B,cAAc,EAAE,kBAAkB,EAClC,cAAc,EAAE,GAAG,EAAE,CAAC,kBAAkB,CAAC,KAAK,CAAC,GAC/C,CACH,CAAC;AACJ,CAAC,CAAC;AAEF,kBAAe,SAAS,CAAC","sourcesContent":["/**\n *\n * Copyright (c) \"Neo4j\"\n * Neo4j Sweden AB [http://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Neo4j is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program. If not, see <http://www.gnu.org/licenses/>.\n */\n\nimport '@neo4j-ndl/base/lib/neo4j-ds-styles.css';\n\nimport { Prompt } from '@neo4j-ndl/react/ai';\nimport { useState } from 'react';\n\nconst Component = () => {\n const [prompt, setPrompt] = useState('');\n const [isRunningPrompt, setIsRunningPrompt] = useState(false);\n\n const handleSubmitPrompt = () => {\n setIsRunningPrompt(true);\n alert(`You submitted the following prompt: ${prompt}`);\n setPrompt('');\n };\n\n return (\n <Prompt\n isRunningPrompt={isRunningPrompt}\n value={prompt}\n onChange={(e: React.ChangeEvent<HTMLTextAreaElement>) =>\n setPrompt(e.target.value)\n }\n onSubmitPrompt={handleSubmitPrompt}\n onCancelPrompt={() => setIsRunningPrompt(false)}\n />\n );\n};\n\nexport default Component;\n"]}
|
|
@@ -67,28 +67,26 @@ const Component = () => {
|
|
|
67
67
|
(0, react_2.useEffect)(() => {
|
|
68
68
|
scrollToBottom();
|
|
69
69
|
}, [messages, isThinking]);
|
|
70
|
-
const
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
if (intervalRef.current) {
|
|
77
|
-
clearInterval(intervalRef.current);
|
|
78
|
-
}
|
|
79
|
-
setIsThinking(false);
|
|
80
|
-
setIsStreaming(false);
|
|
81
|
-
// Mark the last message as done if stopped
|
|
82
|
-
setMessages((prev) => {
|
|
83
|
-
const newMessages = [...prev];
|
|
84
|
-
const lastMessage = newMessages[newMessages.length - 1];
|
|
85
|
-
if ((lastMessage === null || lastMessage === void 0 ? void 0 : lastMessage.role) === 'assistant') {
|
|
86
|
-
lastMessage.done = true;
|
|
87
|
-
}
|
|
88
|
-
return newMessages;
|
|
89
|
-
});
|
|
90
|
-
return;
|
|
70
|
+
const handleCancel = () => {
|
|
71
|
+
if (timeoutRef.current) {
|
|
72
|
+
clearTimeout(timeoutRef.current);
|
|
73
|
+
}
|
|
74
|
+
if (intervalRef.current) {
|
|
75
|
+
clearInterval(intervalRef.current);
|
|
91
76
|
}
|
|
77
|
+
setIsThinking(false);
|
|
78
|
+
setIsStreaming(false);
|
|
79
|
+
// Mark the last message as done if stopped
|
|
80
|
+
setMessages((prev) => {
|
|
81
|
+
const newMessages = [...prev];
|
|
82
|
+
const lastMessage = newMessages[newMessages.length - 1];
|
|
83
|
+
if ((lastMessage === null || lastMessage === void 0 ? void 0 : lastMessage.role) === 'assistant') {
|
|
84
|
+
lastMessage.done = true;
|
|
85
|
+
}
|
|
86
|
+
return newMessages;
|
|
87
|
+
});
|
|
88
|
+
};
|
|
89
|
+
const handleSend = (overridePrompt) => {
|
|
92
90
|
const textToSend = overridePrompt || prompt;
|
|
93
91
|
if (!textToSend.trim()) {
|
|
94
92
|
return;
|
|
@@ -155,7 +153,7 @@ const Component = () => {
|
|
|
155
153
|
}, children: "Generate a report" })] }), (0, jsx_runtime_1.jsxs)(react_1.Typography, { variant: "body-medium", children: ["You can also drag and drop files here, or", ' ', (0, jsx_runtime_1.jsx)(react_1.TextLink, { as: "button", type: "internal-underline", children: "browse" }), ". Supports CVG, MOV, PDF"] })] }) })) : ((0, jsx_runtime_1.jsxs)("div", { className: "n-flex n-flex-col n-gap-4 n-pb-4", children: [messages.map((msg, idx) => ((0, jsx_runtime_1.jsx)("div", { className: `n-flex ${msg.role === 'user' ? 'n-justify-end' : 'n-justify-start'}`, children: msg.role === 'user' ? ((0, jsx_runtime_1.jsx)("div", { className: "n-max-w-[85%]", children: (0, jsx_runtime_1.jsx)(ai_1.UserBubble, { avatarProps: {
|
|
156
154
|
name: 'NM',
|
|
157
155
|
type: 'letters',
|
|
158
|
-
}, children: msg.content }) })) : ((0, jsx_runtime_1.jsxs)("div", { className: "n-w-full n-flex n-flex-col n-gap-2", children: [msg.thinkingTime !== undefined && ((0, jsx_runtime_1.jsx)(ai_1.Thinking, { isThinking: false, thinkingMs: msg.thinkingTime })), (0, jsx_runtime_1.jsxs)("div", { className: "n-flex n-flex-col n-gap-2", children: [(0, jsx_runtime_1.jsx)(ai_1.Response, { children: msg.content }), msg.done === true && ((0, jsx_runtime_1.jsxs)("div", { className: "n-flex n-flex-row n-gap-1.5", children: [(0, jsx_runtime_1.jsx)(react_1.CleanIconButton, { size: "small", description: "Dislike", children: (0, jsx_runtime_1.jsx)(icons_1.HandThumbDownIconOutline, {}) }), (0, jsx_runtime_1.jsx)(react_1.CleanIconButton, { size: "small", description: "Re-run", children: (0, jsx_runtime_1.jsx)(icons_1.ArrowPathIconOutline, {}) }), (0, jsx_runtime_1.jsx)(react_1.CleanIconButton, { size: "small", description: "Copy", children: (0, jsx_runtime_1.jsx)(icons_1.Square2StackIconOutline, {}) })] }))] })] })) }, idx))), isThinking && (0, jsx_runtime_1.jsx)(ai_1.Thinking, { isThinking: true }), (0, jsx_runtime_1.jsx)("div", { ref: messagesEndRef })] })) }), (0, jsx_runtime_1.jsx)("div", { className: "n-px-4 n-pt-4 n-pb-1 n-mt-auto", children: (0, jsx_runtime_1.jsx)(ai_1.Prompt, { value: prompt, onChange: (e) => setPrompt(e.target.value), onSubmitPrompt: () => handleSend(), isRunningPrompt: isThinking || isStreaming, isSubmitDisabled: prompt.length === 0 && !(isThinking || isStreaming), bottomContent: (0, jsx_runtime_1.jsx)(react_1.CleanIconButton, { description: "Add files", size: "small", children: (0, jsx_runtime_1.jsx)(icons_1.PlusIconOutline, {}) }) }) })] }) }));
|
|
156
|
+
}, children: msg.content }) })) : ((0, jsx_runtime_1.jsxs)("div", { className: "n-w-full n-flex n-flex-col n-gap-2", children: [msg.thinkingTime !== undefined && ((0, jsx_runtime_1.jsx)(ai_1.Thinking, { isThinking: false, thinkingMs: msg.thinkingTime })), (0, jsx_runtime_1.jsxs)("div", { className: "n-flex n-flex-col n-gap-2", children: [(0, jsx_runtime_1.jsx)(ai_1.Response, { children: msg.content }), msg.done === true && ((0, jsx_runtime_1.jsxs)("div", { className: "n-flex n-flex-row n-gap-1.5", children: [(0, jsx_runtime_1.jsx)(react_1.CleanIconButton, { size: "small", description: "Dislike", children: (0, jsx_runtime_1.jsx)(icons_1.HandThumbDownIconOutline, {}) }), (0, jsx_runtime_1.jsx)(react_1.CleanIconButton, { size: "small", description: "Re-run", children: (0, jsx_runtime_1.jsx)(icons_1.ArrowPathIconOutline, {}) }), (0, jsx_runtime_1.jsx)(react_1.CleanIconButton, { size: "small", description: "Copy", children: (0, jsx_runtime_1.jsx)(icons_1.Square2StackIconOutline, {}) })] }))] })] })) }, idx))), isThinking && (0, jsx_runtime_1.jsx)(ai_1.Thinking, { isThinking: true }), (0, jsx_runtime_1.jsx)("div", { ref: messagesEndRef })] })) }), (0, jsx_runtime_1.jsx)("div", { className: "n-px-4 n-pt-4 n-pb-1 n-mt-auto", children: (0, jsx_runtime_1.jsx)(ai_1.Prompt, { value: prompt, onChange: (e) => setPrompt(e.target.value), onSubmitPrompt: () => handleSend(), onCancelPrompt: handleCancel, isRunningPrompt: isThinking || isStreaming, isSubmitDisabled: prompt.length === 0 && !(isThinking || isStreaming), bottomContent: (0, jsx_runtime_1.jsx)(react_1.CleanIconButton, { description: "Add files", size: "small", children: (0, jsx_runtime_1.jsx)(icons_1.PlusIconOutline, {}) }) }) })] }) }));
|
|
159
157
|
};
|
|
160
158
|
exports.Component = Component;
|
|
161
159
|
exports.default = exports.Component;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"response-full-example.story.js","sourceRoot":"","sources":["../../../../../src/ai/response/stories/response-full-example.story.tsx"],"names":[],"mappings":"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","sourcesContent":["/**\n *\n * Copyright (c) \"Neo4j\"\n * Neo4j Sweden AB [http://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Neo4j is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program. If not, see <http://www.gnu.org/licenses/>.\n */\nimport { CleanIconButton, TextLink, Typography } from '@neo4j-ndl/react';\nimport {\n Prompt,\n Response,\n Suggestion,\n Thinking,\n UserBubble,\n} from '@neo4j-ndl/react/ai';\nimport {\n ArrowPathIconOutline,\n Cog6ToothIconOutline,\n HandThumbDownIconOutline,\n PlusIconOutline,\n Square2StackIconOutline,\n XMarkIconOutline,\n} from '@neo4j-ndl/react/icons';\nimport { useEffect, useRef, useState } from 'react';\n\nconst FAKE_RESPONSES = [\n `Here is a simple response with some **bold text** and *italics*.`,\n `Here is a list of items:\n- Item 1\n- Item 2\n- Item 3`,\n `Here is a code block example:\n\n\\`\\`\\`typescript\nconst greeting = \"Hello World\";\nconsole.log(greeting);\n\\`\\`\\`\n`,\n `# Heading 1\n## Heading 2\n### Heading 3\n\nSome text under headings.`,\n `You can also use tables:\n\n| Header 1 | Header 2 |\n|Data 1|Data 2|\n|Data 3|Data 4|\n`,\n];\n\nexport const Component = () => {\n const [messages, setMessages] = useState<\n {\n role: 'user' | 'assistant';\n content: string;\n thinkingTime?: number;\n done?: boolean;\n }[]\n >([]);\n const [prompt, setPrompt] = useState('');\n const [isThinking, setIsThinking] = useState(false);\n const [isStreaming, setIsStreaming] = useState(false);\n const [responseIndex, setResponseIndex] = useState(0);\n const messagesEndRef = useRef<HTMLDivElement>(null);\n const timeoutRef = useRef<NodeJS.Timeout | null>(null);\n const intervalRef = useRef<NodeJS.Timeout | null>(null);\n\n const scrollToBottom = () => {\n messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });\n };\n\n useEffect(() => {\n scrollToBottom();\n }, [messages, isThinking]);\n\n const handleSend = (overridePrompt?: string) => {\n // Handle Stop\n if (isThinking || isStreaming) {\n if (timeoutRef.current) {\n clearTimeout(timeoutRef.current);\n }\n if (intervalRef.current) {\n clearInterval(intervalRef.current);\n }\n setIsThinking(false);\n setIsStreaming(false);\n\n // Mark the last message as done if stopped\n setMessages((prev) => {\n const newMessages = [...prev];\n const lastMessage = newMessages[newMessages.length - 1];\n if (lastMessage?.role === 'assistant') {\n lastMessage.done = true;\n }\n return newMessages;\n });\n return;\n }\n\n const textToSend = overridePrompt || prompt;\n\n if (!textToSend.trim()) {\n return;\n }\n\n setMessages((prev) => [...prev, { content: textToSend, role: 'user' }]);\n setPrompt('');\n setIsThinking(true);\n const startTime = Date.now();\n\n // Simulate network delay (thinking time)\n timeoutRef.current = setTimeout(() => {\n const endTime = Date.now();\n const thinkingTime = endTime - startTime;\n setIsThinking(false);\n setIsStreaming(true);\n\n const responseText = FAKE_RESPONSES[responseIndex];\n setResponseIndex((prev) => (prev + 1) % FAKE_RESPONSES.length);\n\n let currentText = '';\n setMessages((prev) => [\n ...prev,\n { content: '', done: false, role: 'assistant', thinkingTime },\n ]);\n\n // Simulate streaming\n intervalRef.current = setInterval(() => {\n if (currentText.length < responseText.length) {\n // Add a few characters at a time to simulate chunks\n // Ensure we don't split newlines incorrectly if that's an issue,\n // but simple slicing should be fine as long as the source has \\n.\n const chunk = responseText.slice(\n currentText.length,\n currentText.length + 2,\n );\n currentText += chunk;\n\n setMessages((prev) => {\n const newMessages = [...prev];\n const lastMessage = newMessages[newMessages.length - 1];\n if (lastMessage.role === 'assistant') {\n lastMessage.content = currentText;\n }\n return newMessages;\n });\n } else {\n if (intervalRef.current) {\n clearInterval(intervalRef.current);\n }\n setIsStreaming(false);\n setMessages((prev) => {\n const newMessages = [...prev];\n const lastMessage = newMessages[newMessages.length - 1];\n if (lastMessage.role === 'assistant') {\n lastMessage.done = true;\n }\n return newMessages;\n });\n }\n }, 50);\n }, 2000);\n };\n\n return (\n <section className=\"n-h-screen\">\n <div className=\"n-w-[440px] n-h-full n-flex n-flex-col n-bg-neutral-bg-weak\">\n <div className=\"n-flex n-flex-row n-border-b n-border-neutral-border-weak n-p-3\">\n <div className=\"n-ml-auto\">\n <CleanIconButton description=\"settings\" tooltipProps={{}}>\n <Cog6ToothIconOutline />\n </CleanIconButton>\n <CleanIconButton description=\"close\">\n <XMarkIconOutline />\n </CleanIconButton>\n </div>\n </div>\n <div className=\"n-p-4 n-flex n-flex-col n-grow n-overflow-y-auto\">\n {messages.length === 0 ? (\n <div className=\"n-flex n-flex-col \">\n <div className=\"n-flex n-flex-col n-gap-12\">\n <Typography variant=\"display\">\n Hi [User], how can I help you today?\n </Typography>\n <div className=\"n-flex n-flex-col n-gap-4\">\n <Typography variant=\"body-medium\">Suggestions</Typography>\n <Suggestion\n isPrimary\n onClick={() => {\n handleSend('I want to import data');\n }}\n >\n I want to import data\n </Suggestion>\n <Suggestion\n onClick={() => {\n handleSend('Create an AI agent');\n }}\n >\n Create an AI agent\n </Suggestion>\n <Suggestion\n onClick={() => {\n handleSend('Invite project members');\n }}\n >\n Invite project members\n </Suggestion>\n <Suggestion\n onClick={() => {\n handleSend('Generate a report');\n }}\n >\n Generate a report\n </Suggestion>\n </div>\n <Typography variant=\"body-medium\">\n You can also drag and drop files here, or{' '}\n <TextLink as=\"button\" type=\"internal-underline\">\n browse\n </TextLink>\n . Supports CVG, MOV, PDF\n </Typography>\n </div>\n </div>\n ) : (\n <div className=\"n-flex n-flex-col n-gap-4 n-pb-4\">\n {messages.map((msg, idx) => (\n <div\n key={idx}\n className={`n-flex ${\n msg.role === 'user' ? 'n-justify-end' : 'n-justify-start'\n }`}\n >\n {msg.role === 'user' ? (\n <div className=\"n-max-w-[85%]\">\n <UserBubble\n avatarProps={{\n name: 'NM',\n type: 'letters',\n }}\n >\n {msg.content}\n </UserBubble>\n </div>\n ) : (\n <div className=\"n-w-full n-flex n-flex-col n-gap-2\">\n {msg.thinkingTime !== undefined && (\n <Thinking\n isThinking={false}\n thinkingMs={msg.thinkingTime}\n />\n )}\n <div className=\"n-flex n-flex-col n-gap-2\">\n <Response>{msg.content}</Response>\n\n {msg.done === true && (\n <div className=\"n-flex n-flex-row n-gap-1.5\">\n <CleanIconButton size=\"small\" description=\"Dislike\">\n <HandThumbDownIconOutline />\n </CleanIconButton>\n <CleanIconButton size=\"small\" description=\"Re-run\">\n <ArrowPathIconOutline />\n </CleanIconButton>\n <CleanIconButton size=\"small\" description=\"Copy\">\n <Square2StackIconOutline />\n </CleanIconButton>\n </div>\n )}\n </div>\n </div>\n )}\n </div>\n ))}\n {isThinking && <Thinking isThinking={true} />}\n <div ref={messagesEndRef} />\n </div>\n )}\n </div>\n <div className=\"n-px-4 n-pt-4 n-pb-1 n-mt-auto\">\n <Prompt\n value={prompt}\n onChange={(e) => setPrompt(e.target.value)}\n onSubmitPrompt={() => handleSend()}\n isRunningPrompt={isThinking || isStreaming}\n isSubmitDisabled={\n prompt.length === 0 && !(isThinking || isStreaming)\n }\n bottomContent={\n <CleanIconButton description=\"Add files\" size=\"small\">\n <PlusIconOutline />\n </CleanIconButton>\n }\n />\n </div>\n </div>\n </section>\n );\n};\n\nexport default Component;\n"]}
|
|
1
|
+
{"version":3,"file":"response-full-example.story.js","sourceRoot":"","sources":["../../../../../src/ai/response/stories/response-full-example.story.tsx"],"names":[],"mappings":"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","sourcesContent":["/**\n *\n * Copyright (c) \"Neo4j\"\n * Neo4j Sweden AB [http://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Neo4j is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program. If not, see <http://www.gnu.org/licenses/>.\n */\nimport { CleanIconButton, TextLink, Typography } from '@neo4j-ndl/react';\nimport {\n Prompt,\n Response,\n Suggestion,\n Thinking,\n UserBubble,\n} from '@neo4j-ndl/react/ai';\nimport {\n ArrowPathIconOutline,\n Cog6ToothIconOutline,\n HandThumbDownIconOutline,\n PlusIconOutline,\n Square2StackIconOutline,\n XMarkIconOutline,\n} from '@neo4j-ndl/react/icons';\nimport { useEffect, useRef, useState } from 'react';\n\nconst FAKE_RESPONSES = [\n `Here is a simple response with some **bold text** and *italics*.`,\n `Here is a list of items:\n- Item 1\n- Item 2\n- Item 3`,\n `Here is a code block example:\n\n\\`\\`\\`typescript\nconst greeting = \"Hello World\";\nconsole.log(greeting);\n\\`\\`\\`\n`,\n `# Heading 1\n## Heading 2\n### Heading 3\n\nSome text under headings.`,\n `You can also use tables:\n\n| Header 1 | Header 2 |\n|Data 1|Data 2|\n|Data 3|Data 4|\n`,\n];\n\nexport const Component = () => {\n const [messages, setMessages] = useState<\n {\n role: 'user' | 'assistant';\n content: string;\n thinkingTime?: number;\n done?: boolean;\n }[]\n >([]);\n const [prompt, setPrompt] = useState('');\n const [isThinking, setIsThinking] = useState(false);\n const [isStreaming, setIsStreaming] = useState(false);\n const [responseIndex, setResponseIndex] = useState(0);\n const messagesEndRef = useRef<HTMLDivElement>(null);\n const timeoutRef = useRef<NodeJS.Timeout | null>(null);\n const intervalRef = useRef<NodeJS.Timeout | null>(null);\n\n const scrollToBottom = () => {\n messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });\n };\n\n useEffect(() => {\n scrollToBottom();\n }, [messages, isThinking]);\n\n const handleCancel = () => {\n if (timeoutRef.current) {\n clearTimeout(timeoutRef.current);\n }\n if (intervalRef.current) {\n clearInterval(intervalRef.current);\n }\n setIsThinking(false);\n setIsStreaming(false);\n\n // Mark the last message as done if stopped\n setMessages((prev) => {\n const newMessages = [...prev];\n const lastMessage = newMessages[newMessages.length - 1];\n if (lastMessage?.role === 'assistant') {\n lastMessage.done = true;\n }\n return newMessages;\n });\n };\n\n const handleSend = (overridePrompt?: string) => {\n const textToSend = overridePrompt || prompt;\n\n if (!textToSend.trim()) {\n return;\n }\n\n setMessages((prev) => [...prev, { content: textToSend, role: 'user' }]);\n setPrompt('');\n setIsThinking(true);\n const startTime = Date.now();\n\n // Simulate network delay (thinking time)\n timeoutRef.current = setTimeout(() => {\n const endTime = Date.now();\n const thinkingTime = endTime - startTime;\n setIsThinking(false);\n setIsStreaming(true);\n\n const responseText = FAKE_RESPONSES[responseIndex];\n setResponseIndex((prev) => (prev + 1) % FAKE_RESPONSES.length);\n\n let currentText = '';\n setMessages((prev) => [\n ...prev,\n { content: '', done: false, role: 'assistant', thinkingTime },\n ]);\n\n // Simulate streaming\n intervalRef.current = setInterval(() => {\n if (currentText.length < responseText.length) {\n // Add a few characters at a time to simulate chunks\n // Ensure we don't split newlines incorrectly if that's an issue,\n // but simple slicing should be fine as long as the source has \\n.\n const chunk = responseText.slice(\n currentText.length,\n currentText.length + 2,\n );\n currentText += chunk;\n\n setMessages((prev) => {\n const newMessages = [...prev];\n const lastMessage = newMessages[newMessages.length - 1];\n if (lastMessage.role === 'assistant') {\n lastMessage.content = currentText;\n }\n return newMessages;\n });\n } else {\n if (intervalRef.current) {\n clearInterval(intervalRef.current);\n }\n setIsStreaming(false);\n setMessages((prev) => {\n const newMessages = [...prev];\n const lastMessage = newMessages[newMessages.length - 1];\n if (lastMessage.role === 'assistant') {\n lastMessage.done = true;\n }\n return newMessages;\n });\n }\n }, 50);\n }, 2000);\n };\n\n return (\n <section className=\"n-h-screen\">\n <div className=\"n-w-[440px] n-h-full n-flex n-flex-col n-bg-neutral-bg-weak\">\n <div className=\"n-flex n-flex-row n-border-b n-border-neutral-border-weak n-p-3\">\n <div className=\"n-ml-auto\">\n <CleanIconButton description=\"settings\" tooltipProps={{}}>\n <Cog6ToothIconOutline />\n </CleanIconButton>\n <CleanIconButton description=\"close\">\n <XMarkIconOutline />\n </CleanIconButton>\n </div>\n </div>\n <div className=\"n-p-4 n-flex n-flex-col n-grow n-overflow-y-auto\">\n {messages.length === 0 ? (\n <div className=\"n-flex n-flex-col \">\n <div className=\"n-flex n-flex-col n-gap-12\">\n <Typography variant=\"display\">\n Hi [User], how can I help you today?\n </Typography>\n <div className=\"n-flex n-flex-col n-gap-4\">\n <Typography variant=\"body-medium\">Suggestions</Typography>\n <Suggestion\n isPrimary\n onClick={() => {\n handleSend('I want to import data');\n }}\n >\n I want to import data\n </Suggestion>\n <Suggestion\n onClick={() => {\n handleSend('Create an AI agent');\n }}\n >\n Create an AI agent\n </Suggestion>\n <Suggestion\n onClick={() => {\n handleSend('Invite project members');\n }}\n >\n Invite project members\n </Suggestion>\n <Suggestion\n onClick={() => {\n handleSend('Generate a report');\n }}\n >\n Generate a report\n </Suggestion>\n </div>\n <Typography variant=\"body-medium\">\n You can also drag and drop files here, or{' '}\n <TextLink as=\"button\" type=\"internal-underline\">\n browse\n </TextLink>\n . Supports CVG, MOV, PDF\n </Typography>\n </div>\n </div>\n ) : (\n <div className=\"n-flex n-flex-col n-gap-4 n-pb-4\">\n {messages.map((msg, idx) => (\n <div\n key={idx}\n className={`n-flex ${\n msg.role === 'user' ? 'n-justify-end' : 'n-justify-start'\n }`}\n >\n {msg.role === 'user' ? (\n <div className=\"n-max-w-[85%]\">\n <UserBubble\n avatarProps={{\n name: 'NM',\n type: 'letters',\n }}\n >\n {msg.content}\n </UserBubble>\n </div>\n ) : (\n <div className=\"n-w-full n-flex n-flex-col n-gap-2\">\n {msg.thinkingTime !== undefined && (\n <Thinking\n isThinking={false}\n thinkingMs={msg.thinkingTime}\n />\n )}\n <div className=\"n-flex n-flex-col n-gap-2\">\n <Response>{msg.content}</Response>\n\n {msg.done === true && (\n <div className=\"n-flex n-flex-row n-gap-1.5\">\n <CleanIconButton size=\"small\" description=\"Dislike\">\n <HandThumbDownIconOutline />\n </CleanIconButton>\n <CleanIconButton size=\"small\" description=\"Re-run\">\n <ArrowPathIconOutline />\n </CleanIconButton>\n <CleanIconButton size=\"small\" description=\"Copy\">\n <Square2StackIconOutline />\n </CleanIconButton>\n </div>\n )}\n </div>\n </div>\n )}\n </div>\n ))}\n {isThinking && <Thinking isThinking={true} />}\n <div ref={messagesEndRef} />\n </div>\n )}\n </div>\n <div className=\"n-px-4 n-pt-4 n-pb-1 n-mt-auto\">\n <Prompt\n value={prompt}\n onChange={(e) => setPrompt(e.target.value)}\n onSubmitPrompt={() => handleSend()}\n onCancelPrompt={handleCancel}\n isRunningPrompt={isThinking || isStreaming}\n isSubmitDisabled={\n prompt.length === 0 && !(isThinking || isStreaming)\n }\n bottomContent={\n <CleanIconButton description=\"Add files\" size=\"small\">\n <PlusIconOutline />\n </CleanIconButton>\n }\n />\n </div>\n </div>\n </section>\n );\n};\n\nexport default Component;\n"]}
|
|
@@ -42,7 +42,7 @@ import { useCallback, useEffect, useRef, useState } from 'react';
|
|
|
42
42
|
* @alpha - Changes to this component may be breaking.
|
|
43
43
|
*/
|
|
44
44
|
const PromptComponent = (_a) => {
|
|
45
|
-
var { value, onChange, maxRows = 5, isRunningPrompt = false, onSubmitPrompt, isSubmitDisabled = false, topContent, bottomContent, disclaimer = 'All information should be verified.', className, style, htmlAttributes, ref, textareaProps } = _a, restProps = __rest(_a, ["value", "onChange", "maxRows", "isRunningPrompt", "onSubmitPrompt", "isSubmitDisabled", "topContent", "bottomContent", "disclaimer", "className", "style", "htmlAttributes", "ref", "textareaProps"]);
|
|
45
|
+
var { value, onChange, maxRows = 5, isRunningPrompt = false, onSubmitPrompt, onCancelPrompt, isSubmitDisabled = false, topContent, bottomContent, disclaimer = 'All information should be verified.', className, style, htmlAttributes, ref, textareaProps } = _a, restProps = __rest(_a, ["value", "onChange", "maxRows", "isRunningPrompt", "onSubmitPrompt", "onCancelPrompt", "isSubmitDisabled", "topContent", "bottomContent", "disclaimer", "className", "style", "htmlAttributes", "ref", "textareaProps"]);
|
|
46
46
|
const classes = classNames('ndl-ai-prompt', className);
|
|
47
47
|
const textareaRef = useRef(null);
|
|
48
48
|
const textareaAboveRef = useRef(null);
|
|
@@ -124,13 +124,15 @@ const PromptComponent = (_a) => {
|
|
|
124
124
|
!e.shiftKey &&
|
|
125
125
|
isSubmitDisabled !== true) {
|
|
126
126
|
e.preventDefault();
|
|
127
|
-
|
|
127
|
+
if (isRunningPrompt !== true) {
|
|
128
|
+
onSubmitPrompt === null || onSubmitPrompt === void 0 ? void 0 : onSubmitPrompt(e);
|
|
129
|
+
}
|
|
128
130
|
}
|
|
129
|
-
} }, textareaProps)), _jsxs("div", { className: "ndl-ai-prompt-textarea-below", children: [Boolean(bottomContent) && (_jsx("div", { className: "ndl-ai-prompt-textarea-below-leading", children: bottomContent })), _jsx(SumbitPromptButton, { isDisabled: isSubmitDisabled, isRunningPrompt: isRunningPrompt,
|
|
131
|
+
} }, textareaProps)), _jsxs("div", { className: "ndl-ai-prompt-textarea-below", children: [Boolean(bottomContent) && (_jsx("div", { className: "ndl-ai-prompt-textarea-below-leading", children: bottomContent })), _jsx(SumbitPromptButton, { isDisabled: isSubmitDisabled, isRunningPrompt: isRunningPrompt, onSubmit: onSubmitPrompt, onCancel: onCancelPrompt })] })] }) }), Boolean(disclaimer) && (_jsx(Typography, { variant: "body-small", className: "ndl-ai-prompt-footer", children: disclaimer }))] })));
|
|
130
132
|
};
|
|
131
|
-
const SumbitPromptButton = ({
|
|
133
|
+
const SumbitPromptButton = ({ onSubmit, onCancel, isDisabled, isRunningPrompt, }) => {
|
|
132
134
|
const description = isRunningPrompt === true ? 'Cancel' : 'Send';
|
|
133
|
-
return (_jsxs(CleanIconButton, { className: "ndl-ai-prompt-submit-button", description: description, size: "medium", onClick:
|
|
135
|
+
return (_jsxs(CleanIconButton, { className: "ndl-ai-prompt-submit-button", description: description, size: "medium", onClick: isRunningPrompt === true ? onCancel : onSubmit, isDisabled: isDisabled, children: [_jsx(ArrowSmallUpIconOutline, { style: {
|
|
134
136
|
opacity: isRunningPrompt === true ? 0 : 1,
|
|
135
137
|
position: isRunningPrompt === true ? 'absolute' : 'relative',
|
|
136
138
|
transform: isRunningPrompt === true ? 'translateY(-8px)' : 'translateY(0)',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Prompt.js","sourceRoot":"","sources":["../../../../src/ai/prompt/Prompt.tsx"],"names":[],"mappings":";;;;;;;;;;;;AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EACL,eAAe,EACf,cAAc,EACd,IAAI,EACJ,UAAU,GACX,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,uBAAuB,EACvB,gBAAgB,EAChB,qBAAqB,GACtB,MAAM,wBAAwB,CAAC;AAChC,OAAO,UAAU,MAAM,YAAY,CAAC;AACpC,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AA+BjE;;;;;;GAMG;AACH,MAAM,eAAe,GAAG,CAAC,EAgBS,EAAE,EAAE;QAhBb,EACvB,KAAK,EACL,QAAQ,EACR,OAAO,GAAG,CAAC,EACX,eAAe,GAAG,KAAK,EACvB,cAAc,EACd,gBAAgB,GAAG,KAAK,EACxB,UAAU,EACV,aAAa,EACb,UAAU,GAAG,qCAAqC,EAClD,SAAS,EACT,KAAK,EACL,cAAc,EACd,GAAG,EACH,aAAa,OAEmB,EAD7B,SAAS,cAfW,sMAgBxB,CADa;IAEZ,MAAM,OAAO,GAAG,UAAU,CAAC,eAAe,EAAE,SAAS,CAAC,CAAC;IAEvD,MAAM,WAAW,GAAG,MAAM,CAAsB,IAAI,CAAC,CAAC;IACtD,MAAM,gBAAgB,GAAG,MAAM,CAAiB,IAAI,CAAC,CAAC;IACtD,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;IAEhD,0BAA0B;IAC1B,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,KAAK,GAAkB,IAAI,CAAC;QAEhC,MAAM,aAAa,GAAG,GAAG,EAAE;YACzB,IAAI,gBAAgB,CAAC,OAAO,KAAK,IAAI,EAAE,CAAC;gBACtC,MAAM,OAAO,GAAG,gBAAgB,CAAC,OAAO,CAAC;gBACzC,MAAM,SAAS,GAAG,UAAU,CAC1B,gBAAgB,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CACtD,CAAC;gBACF,MAAM,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC;gBAE1C,IAAI,YAAY,GAAG,SAAS,EAAE,CAAC;oBAC7B,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;gBAC1C,CAAC;qBAAM,CAAC;oBACN,OAAO,CAAC,SAAS,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC;gBAC7C,CAAC;YACH,CAAC;QACH,CAAC,CAAC;QAEF,MAAM,cAAc,GAAG,GAAG,EAAE;YAC1B,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;gBACnB,oBAAoB,CAAC,KAAK,CAAC,CAAC;YAC9B,CAAC;YACD,KAAK,GAAG,qBAAqB,CAAC,aAAa,CAAC,CAAC;QAC/C,CAAC,CAAC;QAEF,gBAAgB;QAChB,aAAa,EAAE,CAAC;QAEhB,MAAM,cAAc,GAAG,IAAI,cAAc,CAAC,cAAc,CAAC,CAAC;QAC1D,MAAM,gBAAgB,GAAG,IAAI,gBAAgB,CAAC,cAAc,CAAC,CAAC;QAE9D,IAAI,gBAAgB,CAAC,OAAO,KAAK,IAAI,EAAE,CAAC;YACtC,cAAc,CAAC,OAAO,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC;YACjD,gBAAgB,CAAC,OAAO,CAAC,gBAAgB,CAAC,OAAO,EAAE;gBACjD,SAAS,EAAE,IAAI;gBACf,OAAO,EAAE,IAAI;aACd,CAAC,CAAC;QACL,CAAC;QAED,OAAO,GAAG,EAAE;YACV,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;gBACnB,oBAAoB,CAAC,KAAK,CAAC,CAAC;YAC9B,CAAC;YACD,cAAc,CAAC,UAAU,EAAE,CAAC;YAC5B,gBAAgB,CAAC,UAAU,EAAE,CAAC;QAChC,CAAC,CAAC;IACJ,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,qBAAqB;IACrB,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,WAAW,CAAC,OAAO,KAAK,IAAI,EAAE,CAAC;YACjC,MAAM,QAAQ,GAAG,MAAM,CAAC,gBAAgB,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;YAC9D,aAAa,CAAC,QAAQ,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC;QAC/C,CAAC;IACH,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,MAAM,oBAAoB,GAAG,WAAW,CAAC,GAAG,EAAE;QAC5C,MAAM,EAAE,GAAG,WAAW,CAAC,OAAO,CAAC;QAE/B,IAAI,EAAE,KAAK,IAAI,IAAI,UAAU,GAAG,CAAC,EAAE,CAAC;YAClC,kDAAkD;YAClD,EAAE,CAAC,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC;YAEzB,MAAM,SAAS,GAAG,UAAU,GAAG,OAAO,CAAC;YAEvC,IAAI,EAAE,CAAC,YAAY,IAAI,SAAS,EAAE,CAAC;gBACjC,EAAE,CAAC,KAAK,CAAC,SAAS,GAAG,QAAQ,CAAC;gBAC9B,EAAE,CAAC,KAAK,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,IAAI,CAAC;YAC3C,CAAC;iBAAM,CAAC;gBACN,EAAE,CAAC,KAAK,CAAC,SAAS,GAAG,MAAM,CAAC;gBAC5B,EAAE,CAAC,KAAK,CAAC,MAAM,GAAG,GAAG,SAAS,IAAI,CAAC;YACrC,CAAC;QACH,CAAC;IACH,CAAC,EAAE,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC;IAE1B,mEAAmE;IACnE,SAAS,CAAC,GAAG,EAAE;QACb,oBAAoB,EAAE,CAAC;IACzB,CAAC,EAAE,CAAC,KAAK,EAAE,oBAAoB,CAAC,CAAC,CAAC;IAElC,MAAM,WAAW,GAAG,CAAC,CAAyC,EAAE,EAAE;QAChE,oBAAoB,EAAE,CAAC;QACvB,QAAQ,aAAR,QAAQ,uBAAR,QAAQ,CAAG,CAAC,CAAC,CAAC;IAChB,CAAC,CAAC;IAEF,OAAO,CACL,6BACE,GAAG,EAAE,GAAG,EACR,SAAS,EAAE,OAAO,EAClB,KAAK,EAAE,KAAK,IACR,SAAS,EACT,cAAc,eAElB,cAAK,SAAS,EAAC,uBAAuB,YACpC,eAAK,SAAS,EAAC,6BAA6B,aACzC,OAAO,CAAC,UAAU,CAAC,IAAI,CACtB,cACE,SAAS,EAAC,8BAA8B,EACxC,GAAG,EAAE,gBAAgB,YAEpB,UAAU,GACP,CACP,EACD,iCACE,WAAW,EAAC,cAAc,EAC1B,SAAS,EAAC,wBAAwB,EAClC,IAAI,EAAE,CAAC,EACP,QAAQ,EAAE,WAAW,EACrB,KAAK,EAAE,KAAK,EACZ,GAAG,EAAE,WAAW,EAChB,SAAS,EAAE,CAAC,CAAC,EAAE,EAAE;gCACf,IACE,CAAC,CAAC,GAAG,KAAK,OAAO;oCACjB,CAAC,CAAC,CAAC,QAAQ;oCACX,gBAAgB,KAAK,IAAI,EACzB,CAAC;oCACD,CAAC,CAAC,cAAc,EAAE,CAAC;oCACnB,cAAc,aAAd,cAAc,uBAAd,cAAc,CAAG,CAAC,CAAC,CAAC;gCACtB,CAAC;4BACH,CAAC,IACG,aAAa,EACjB,EACF,eAAK,SAAS,EAAC,8BAA8B,aAC1C,OAAO,CAAC,aAAa,CAAC,IAAI,CACzB,cAAK,SAAS,EAAC,sCAAsC,YAClD,aAAa,GACV,CACP,EACD,KAAC,kBAAkB,IACjB,UAAU,EAAE,gBAAgB,EAC5B,eAAe,EAAE,eAAe,EAChC,OAAO,EAAE,cAAc,GACvB,IACE,IACF,GACF,EACL,OAAO,CAAC,UAAU,CAAC,IAAI,CACtB,KAAC,UAAU,IAAC,OAAO,EAAC,YAAY,EAAC,SAAS,EAAC,sBAAsB,YAC9D,UAAU,GACA,CACd,KACG,CACP,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,kBAAkB,GAAG,CAAC,EAC1B,OAAO,EACP,UAAU,EACV,eAAe,GAKhB,EAAE,EAAE;IACH,MAAM,WAAW,GAAG,eAAe,KAAK,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC;IAEjE,OAAO,CACL,MAAC,eAAe,IACd,SAAS,EAAC,6BAA6B,EACvC,WAAW,EAAE,WAAW,EACxB,IAAI,EAAC,QAAQ,EACb,OAAO,EAAE,OAAO,EAChB,UAAU,EAAE,UAAU,aAEtB,KAAC,uBAAuB,IACtB,KAAK,EAAE;oBACL,OAAO,EAAE,eAAe,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;oBACzC,QAAQ,EAAE,eAAe,KAAK,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,UAAU;oBAC5D,SAAS,EACP,eAAe,KAAK,IAAI,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,eAAe;iBAClE,GACD,EACF,KAAC,qBAAqB,IACpB,KAAK,EAAE;oBACL,OAAO,EAAE,eAAe,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;oBACzC,QAAQ,EAAE,eAAe,KAAK,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,UAAU;iBAC7D,GACD,IACc,CACnB,CAAC;AACJ,CAAC,CAAC;AAQF,MAAM,WAAW,GAAG,CAAC,EAAE,KAAK,EAAE,OAAO,GAAG,EAAE,EAAE,QAAQ,EAAoB,EAAE,EAAE;;IAC1E,MAAM,SAAS,GAAG,MAAM,CAAoB,IAAI,CAAC,CAAC;IAClD,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAEpD,MAAM,YAAY,GAAG,MAAA,MAAA,KAAK,aAAL,KAAK,uBAAL,KAAK,CAAE,KAAK,mCAAI,MAAA,OAAO,CAAC,CAAC,CAAC,0CAAE,KAAK,mCAAI,EAAE,CAAC;IAE7D,MAAM,eAAe,GAAG,CAAC,MAGxB,EAAE,EAAE;QACH,QAAQ,aAAR,QAAQ,uBAAR,QAAQ,CAAG,MAAM,CAAC,CAAC;QACnB,aAAa,CAAC,KAAK,CAAC,CAAC;IACvB,CAAC,CAAC;IAEF,OAAO,CACL,8BACE,KAAC,cAAc,IACb,IAAI,EAAC,OAAO,EACZ,SAAS,EAAC,+BAA+B,EACzC,OAAO,EAAE,GAAG,EAAE,CAAC,aAAa,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,EAC3C,MAAM,EAAE,UAAU,EAClB,GAAG,EAAE,SAAS,YAEb,YAAY,GACE,EACjB,KAAC,IAAI,IACH,MAAM,EAAE,UAAU,EAClB,OAAO,EAAE,GAAG,EAAE,CAAC,aAAa,CAAC,KAAK,CAAC,EACnC,SAAS,EAAE,SAAS,EACpB,SAAS,EAAC,wBAAwB,YAElC,KAAC,IAAI,CAAC,KAAK,cACR,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CACvB,KAAC,IAAI,CAAC,IAAI,IAER,KAAK,EAAE,MAAM,CAAC,KAAK,EACnB,OAAO,EAAE,GAAG,EAAE,CAAC,eAAe,CAAC,MAAM,CAAC,EACtC,aAAa,EACX,CAAA,KAAK,aAAL,KAAK,uBAAL,KAAK,CAAE,KAAK,MAAK,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,KAAC,gBAAgB,KAAG,CAAC,CAAC,CAAC,IAAI,IAJxD,MAAM,CAAC,KAAK,CAMjB,CACH,CAAC,GACS,GACR,IACN,CACJ,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,eAAe,EAAE;IAC5C,MAAM,EAAE,WAAW;CACpB,CAAC,CAAC;AAEH,OAAO,EAAE,MAAM,EAAE,CAAC","sourcesContent":["/**\n *\n * Copyright (c) \"Neo4j\"\n * Neo4j Sweden AB [http://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Neo4j is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program. If not, see <http://www.gnu.org/licenses/>.\n */\n\nimport {\n CleanIconButton,\n DropdownButton,\n Menu,\n Typography,\n} from '@neo4j-ndl/react';\nimport {\n ArrowSmallUpIconOutline,\n CheckIconOutline,\n StopCircleIconOutline,\n} from '@neo4j-ndl/react/icons';\nimport classNames from 'classnames';\nimport { useCallback, useEffect, useRef, useState } from 'react';\n\nimport type { CommonProps, HtmlAttributes } from '../../_common/types';\n\ntype PromptProps = {\n /** The prompt text */\n value?: React.ComponentPropsWithoutRef<'textarea'>['value'];\n /** Callback function called when the prompt text changes */\n onChange?: (e: React.ChangeEvent<HTMLTextAreaElement>) => void;\n /** Whether the submit button is disabled */\n isSubmitDisabled?: boolean;\n /** Maximum number of rows the textarea can expand to */\n maxRows?: number;\n /** Whether the submit button is \"running\". Shows a stop icon when true. */\n isRunningPrompt?: boolean;\n /** Callback function called when the submit button is clicked */\n onSubmitPrompt?: (\n e:\n | React.KeyboardEvent<HTMLTextAreaElement>\n | React.MouseEvent<HTMLButtonElement, MouseEvent>,\n ) => void;\n /** Content to display above the textarea */\n topContent?: React.ReactNode;\n /** Content to display below the textarea */\n bottomContent?: React.ReactNode;\n /** Disclaimer to display below the component */\n disclaimer?: React.ReactNode;\n /** Props for the textarea element */\n textareaProps?: HtmlAttributes<'textarea'>;\n};\n\n/**\n * The component is used to display the prompt input for an LLM.\n * It includes a textarea for the user to enter their prompt and a submit button.\n * It can also display content above and below the textarea, like uploaded files or a select for changing agents.\n *\n * @alpha - Changes to this component may be breaking.\n */\nconst PromptComponent = ({\n value,\n onChange,\n maxRows = 5,\n isRunningPrompt = false,\n onSubmitPrompt,\n isSubmitDisabled = false,\n topContent,\n bottomContent,\n disclaimer = 'All information should be verified.',\n className,\n style,\n htmlAttributes,\n ref,\n textareaProps,\n ...restProps\n}: CommonProps<'div', PromptProps>) => {\n const classes = classNames('ndl-ai-prompt', className);\n\n const textareaRef = useRef<HTMLTextAreaElement>(null);\n const textareaAboveRef = useRef<HTMLDivElement>(null);\n const [lineHeight, setLineHeight] = useState(0);\n\n /** File overflow stuff */\n useEffect(() => {\n let rafId: number | null = null;\n\n const checkOverflow = () => {\n if (textareaAboveRef.current !== null) {\n const element = textareaAboveRef.current;\n const maxHeight = parseFloat(\n getComputedStyle(element).maxHeight.replace('px', ''),\n );\n const scrollHeight = element.scrollHeight;\n\n if (scrollHeight > maxHeight) {\n element.classList.add('ndl-can-scroll');\n } else {\n element.classList.remove('ndl-can-scroll');\n }\n }\n };\n\n const debouncedCheck = () => {\n if (rafId !== null) {\n cancelAnimationFrame(rafId);\n }\n rafId = requestAnimationFrame(checkOverflow);\n };\n\n // Initial check\n checkOverflow();\n\n const resizeObserver = new ResizeObserver(debouncedCheck);\n const mutationObserver = new MutationObserver(debouncedCheck);\n\n if (textareaAboveRef.current !== null) {\n resizeObserver.observe(textareaAboveRef.current);\n mutationObserver.observe(textareaAboveRef.current, {\n childList: true,\n subtree: true,\n });\n }\n\n return () => {\n if (rafId !== null) {\n cancelAnimationFrame(rafId);\n }\n resizeObserver.disconnect();\n mutationObserver.disconnect();\n };\n }, []);\n\n /** Textarea stuff */\n useEffect(() => {\n if (textareaRef.current !== null) {\n const computed = window.getComputedStyle(textareaRef.current);\n setLineHeight(parseInt(computed.lineHeight));\n }\n }, []);\n\n const adjustTextareaHeight = useCallback(() => {\n const ta = textareaRef.current;\n\n if (ta !== null && lineHeight > 0) {\n // Reset height so scrollHeight measures correctly\n ta.style.height = 'auto';\n\n const maxHeight = lineHeight * maxRows;\n\n if (ta.scrollHeight <= maxHeight) {\n ta.style.overflowY = 'hidden';\n ta.style.height = `${ta.scrollHeight}px`;\n } else {\n ta.style.overflowY = 'auto';\n ta.style.height = `${maxHeight}px`;\n }\n }\n }, [lineHeight, maxRows]);\n\n // Adjust height when prompt value changes (including when cleared)\n useEffect(() => {\n adjustTextareaHeight();\n }, [value, adjustTextareaHeight]);\n\n const handleInput = (e: React.ChangeEvent<HTMLTextAreaElement>) => {\n adjustTextareaHeight();\n onChange?.(e);\n };\n\n return (\n <div\n ref={ref}\n className={classes}\n style={style}\n {...restProps}\n {...htmlAttributes}\n >\n <div className=\"ndl-ai-prompt-wrapper\">\n <div className=\"ndl-ai-prompt-wrapper-inner\">\n {Boolean(topContent) && (\n <div\n className=\"ndl-ai-prompt-textarea-above\"\n ref={textareaAboveRef}\n >\n {topContent}\n </div>\n )}\n <textarea\n placeholder=\"Ask anything\"\n className=\"ndl-ai-prompt-textarea\"\n rows={1}\n onChange={handleInput}\n value={value}\n ref={textareaRef}\n onKeyDown={(e) => {\n if (\n e.key === 'Enter' &&\n !e.shiftKey &&\n isSubmitDisabled !== true\n ) {\n e.preventDefault();\n onSubmitPrompt?.(e);\n }\n }}\n {...textareaProps}\n />\n <div className=\"ndl-ai-prompt-textarea-below\">\n {Boolean(bottomContent) && (\n <div className=\"ndl-ai-prompt-textarea-below-leading\">\n {bottomContent}\n </div>\n )}\n <SumbitPromptButton\n isDisabled={isSubmitDisabled}\n isRunningPrompt={isRunningPrompt}\n onClick={onSubmitPrompt}\n />\n </div>\n </div>\n </div>\n {Boolean(disclaimer) && (\n <Typography variant=\"body-small\" className=\"ndl-ai-prompt-footer\">\n {disclaimer}\n </Typography>\n )}\n </div>\n );\n};\n\nconst SumbitPromptButton = ({\n onClick,\n isDisabled,\n isRunningPrompt,\n}: {\n isDisabled?: boolean;\n isRunningPrompt?: boolean;\n onClick?: (e: React.MouseEvent<HTMLButtonElement, MouseEvent>) => void;\n}) => {\n const description = isRunningPrompt === true ? 'Cancel' : 'Send';\n\n return (\n <CleanIconButton\n className=\"ndl-ai-prompt-submit-button\"\n description={description}\n size=\"medium\"\n onClick={onClick}\n isDisabled={isDisabled}\n >\n <ArrowSmallUpIconOutline\n style={{\n opacity: isRunningPrompt === true ? 0 : 1,\n position: isRunningPrompt === true ? 'absolute' : 'relative',\n transform:\n isRunningPrompt === true ? 'translateY(-8px)' : 'translateY(0)',\n }}\n />\n <StopCircleIconOutline\n style={{\n opacity: isRunningPrompt === true ? 1 : 0,\n position: isRunningPrompt === true ? 'relative' : 'absolute',\n }}\n />\n </CleanIconButton>\n );\n};\n\ntype AgentSelectProps = {\n value: { label: React.ReactNode; value: string };\n options: Array<{ label: React.ReactNode; value: string }>;\n onChange: (option: { label: React.ReactNode; value: string }) => void;\n};\n\nconst AgentSelect = ({ value, options = [], onChange }: AgentSelectProps) => {\n const anchorRef = useRef<HTMLButtonElement>(null);\n const [isMenuOpen, setIsMenuOpen] = useState(false);\n\n const displayLabel = value?.label ?? options[0]?.label ?? '';\n\n const handleItemClick = (option: {\n label: React.ReactNode;\n value: string;\n }) => {\n onChange?.(option);\n setIsMenuOpen(false);\n };\n\n return (\n <>\n <DropdownButton\n size=\"small\"\n className=\"ndl-ai-prompt-dropdown-button\"\n onClick={() => setIsMenuOpen((old) => !old)}\n isOpen={isMenuOpen}\n ref={anchorRef}\n >\n {displayLabel}\n </DropdownButton>\n <Menu\n isOpen={isMenuOpen}\n onClose={() => setIsMenuOpen(false)}\n anchorRef={anchorRef}\n placement=\"top-start-bottom-start\"\n >\n <Menu.Items>\n {options.map((option) => (\n <Menu.Item\n key={option.value}\n title={option.label}\n onClick={() => handleItemClick(option)}\n leadingVisual={\n value?.value === option.value ? <CheckIconOutline /> : null\n }\n />\n ))}\n </Menu.Items>\n </Menu>\n </>\n );\n};\n\nconst Prompt = Object.assign(PromptComponent, {\n Select: AgentSelect,\n});\n\nexport { Prompt };\n"]}
|
|
1
|
+
{"version":3,"file":"Prompt.js","sourceRoot":"","sources":["../../../../src/ai/prompt/Prompt.tsx"],"names":[],"mappings":"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","sourcesContent":["/**\n *\n * Copyright (c) \"Neo4j\"\n * Neo4j Sweden AB [http://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Neo4j is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program. If not, see <http://www.gnu.org/licenses/>.\n */\n\nimport {\n CleanIconButton,\n DropdownButton,\n Menu,\n Typography,\n} from '@neo4j-ndl/react';\nimport {\n ArrowSmallUpIconOutline,\n CheckIconOutline,\n StopCircleIconOutline,\n} from '@neo4j-ndl/react/icons';\nimport classNames from 'classnames';\nimport { useCallback, useEffect, useRef, useState } from 'react';\n\nimport type { CommonProps, HtmlAttributes } from '../../_common/types';\n\ntype PromptProps = {\n /** The prompt text */\n value?: React.ComponentPropsWithoutRef<'textarea'>['value'];\n /** Callback function called when the prompt text changes */\n onChange?: (e: React.ChangeEvent<HTMLTextAreaElement>) => void;\n /** Whether the submit button is disabled */\n isSubmitDisabled?: boolean;\n /** Maximum number of rows the textarea can expand to */\n maxRows?: number;\n /** Whether the submit button is \"running\". Shows a stop icon when true. */\n isRunningPrompt?: boolean;\n /** Callback function called when the submit button is clicked */\n onSubmitPrompt?: (\n e:\n | React.KeyboardEvent<HTMLTextAreaElement>\n | React.MouseEvent<HTMLButtonElement, MouseEvent>,\n ) => void;\n /** Callback function called when the cancel button is clicked */\n onCancelPrompt?: (e: React.MouseEvent<HTMLButtonElement, MouseEvent>) => void;\n /** Content to display above the textarea */\n topContent?: React.ReactNode;\n /** Content to display below the textarea */\n bottomContent?: React.ReactNode;\n /** Disclaimer to display below the component */\n disclaimer?: React.ReactNode;\n /** Props for the textarea element */\n textareaProps?: HtmlAttributes<'textarea'>;\n};\n\n/**\n * The component is used to display the prompt input for an LLM.\n * It includes a textarea for the user to enter their prompt and a submit button.\n * It can also display content above and below the textarea, like uploaded files or a select for changing agents.\n *\n * @alpha - Changes to this component may be breaking.\n */\nconst PromptComponent = ({\n value,\n onChange,\n maxRows = 5,\n isRunningPrompt = false,\n onSubmitPrompt,\n onCancelPrompt,\n isSubmitDisabled = false,\n topContent,\n bottomContent,\n disclaimer = 'All information should be verified.',\n className,\n style,\n htmlAttributes,\n ref,\n textareaProps,\n ...restProps\n}: CommonProps<'div', PromptProps>) => {\n const classes = classNames('ndl-ai-prompt', className);\n\n const textareaRef = useRef<HTMLTextAreaElement>(null);\n const textareaAboveRef = useRef<HTMLDivElement>(null);\n const [lineHeight, setLineHeight] = useState(0);\n\n /** File overflow stuff */\n useEffect(() => {\n let rafId: number | null = null;\n\n const checkOverflow = () => {\n if (textareaAboveRef.current !== null) {\n const element = textareaAboveRef.current;\n const maxHeight = parseFloat(\n getComputedStyle(element).maxHeight.replace('px', ''),\n );\n const scrollHeight = element.scrollHeight;\n\n if (scrollHeight > maxHeight) {\n element.classList.add('ndl-can-scroll');\n } else {\n element.classList.remove('ndl-can-scroll');\n }\n }\n };\n\n const debouncedCheck = () => {\n if (rafId !== null) {\n cancelAnimationFrame(rafId);\n }\n rafId = requestAnimationFrame(checkOverflow);\n };\n\n // Initial check\n checkOverflow();\n\n const resizeObserver = new ResizeObserver(debouncedCheck);\n const mutationObserver = new MutationObserver(debouncedCheck);\n\n if (textareaAboveRef.current !== null) {\n resizeObserver.observe(textareaAboveRef.current);\n mutationObserver.observe(textareaAboveRef.current, {\n childList: true,\n subtree: true,\n });\n }\n\n return () => {\n if (rafId !== null) {\n cancelAnimationFrame(rafId);\n }\n resizeObserver.disconnect();\n mutationObserver.disconnect();\n };\n }, []);\n\n /** Textarea stuff */\n useEffect(() => {\n if (textareaRef.current !== null) {\n const computed = window.getComputedStyle(textareaRef.current);\n setLineHeight(parseInt(computed.lineHeight));\n }\n }, []);\n\n const adjustTextareaHeight = useCallback(() => {\n const ta = textareaRef.current;\n\n if (ta !== null && lineHeight > 0) {\n // Reset height so scrollHeight measures correctly\n ta.style.height = 'auto';\n\n const maxHeight = lineHeight * maxRows;\n\n if (ta.scrollHeight <= maxHeight) {\n ta.style.overflowY = 'hidden';\n ta.style.height = `${ta.scrollHeight}px`;\n } else {\n ta.style.overflowY = 'auto';\n ta.style.height = `${maxHeight}px`;\n }\n }\n }, [lineHeight, maxRows]);\n\n // Adjust height when prompt value changes (including when cleared)\n useEffect(() => {\n adjustTextareaHeight();\n }, [value, adjustTextareaHeight]);\n\n const handleInput = (e: React.ChangeEvent<HTMLTextAreaElement>) => {\n adjustTextareaHeight();\n onChange?.(e);\n };\n\n return (\n <div\n ref={ref}\n className={classes}\n style={style}\n {...restProps}\n {...htmlAttributes}\n >\n <div className=\"ndl-ai-prompt-wrapper\">\n <div className=\"ndl-ai-prompt-wrapper-inner\">\n {Boolean(topContent) && (\n <div\n className=\"ndl-ai-prompt-textarea-above\"\n ref={textareaAboveRef}\n >\n {topContent}\n </div>\n )}\n <textarea\n placeholder=\"Ask anything\"\n className=\"ndl-ai-prompt-textarea\"\n rows={1}\n onChange={handleInput}\n value={value}\n ref={textareaRef}\n onKeyDown={(e) => {\n if (\n e.key === 'Enter' &&\n !e.shiftKey &&\n isSubmitDisabled !== true\n ) {\n e.preventDefault();\n\n if (isRunningPrompt !== true) {\n onSubmitPrompt?.(e);\n }\n }\n }}\n {...textareaProps}\n />\n <div className=\"ndl-ai-prompt-textarea-below\">\n {Boolean(bottomContent) && (\n <div className=\"ndl-ai-prompt-textarea-below-leading\">\n {bottomContent}\n </div>\n )}\n <SumbitPromptButton\n isDisabled={isSubmitDisabled}\n isRunningPrompt={isRunningPrompt}\n onSubmit={onSubmitPrompt}\n onCancel={onCancelPrompt}\n />\n </div>\n </div>\n </div>\n {Boolean(disclaimer) && (\n <Typography variant=\"body-small\" className=\"ndl-ai-prompt-footer\">\n {disclaimer}\n </Typography>\n )}\n </div>\n );\n};\n\nconst SumbitPromptButton = ({\n onSubmit,\n onCancel,\n isDisabled,\n isRunningPrompt,\n}: {\n isDisabled?: boolean;\n isRunningPrompt?: boolean;\n onSubmit?: (e: React.MouseEvent<HTMLButtonElement, MouseEvent>) => void;\n onCancel?: (e: React.MouseEvent<HTMLButtonElement, MouseEvent>) => void;\n}) => {\n const description = isRunningPrompt === true ? 'Cancel' : 'Send';\n\n return (\n <CleanIconButton\n className=\"ndl-ai-prompt-submit-button\"\n description={description}\n size=\"medium\"\n onClick={isRunningPrompt === true ? onCancel : onSubmit}\n isDisabled={isDisabled}\n >\n <ArrowSmallUpIconOutline\n style={{\n opacity: isRunningPrompt === true ? 0 : 1,\n position: isRunningPrompt === true ? 'absolute' : 'relative',\n transform:\n isRunningPrompt === true ? 'translateY(-8px)' : 'translateY(0)',\n }}\n />\n <StopCircleIconOutline\n style={{\n opacity: isRunningPrompt === true ? 1 : 0,\n position: isRunningPrompt === true ? 'relative' : 'absolute',\n }}\n />\n </CleanIconButton>\n );\n};\n\ntype AgentSelectProps = {\n value: { label: React.ReactNode; value: string };\n options: Array<{ label: React.ReactNode; value: string }>;\n onChange: (option: { label: React.ReactNode; value: string }) => void;\n};\n\nconst AgentSelect = ({ value, options = [], onChange }: AgentSelectProps) => {\n const anchorRef = useRef<HTMLButtonElement>(null);\n const [isMenuOpen, setIsMenuOpen] = useState(false);\n\n const displayLabel = value?.label ?? options[0]?.label ?? '';\n\n const handleItemClick = (option: {\n label: React.ReactNode;\n value: string;\n }) => {\n onChange?.(option);\n setIsMenuOpen(false);\n };\n\n return (\n <>\n <DropdownButton\n size=\"small\"\n className=\"ndl-ai-prompt-dropdown-button\"\n onClick={() => setIsMenuOpen((old) => !old)}\n isOpen={isMenuOpen}\n ref={anchorRef}\n >\n {displayLabel}\n </DropdownButton>\n <Menu\n isOpen={isMenuOpen}\n onClose={() => setIsMenuOpen(false)}\n anchorRef={anchorRef}\n placement=\"top-start-bottom-start\"\n >\n <Menu.Items>\n {options.map((option) => (\n <Menu.Item\n key={option.value}\n title={option.label}\n onClick={() => handleItemClick(option)}\n leadingVisual={\n value?.value === option.value ? <CheckIconOutline /> : null\n }\n />\n ))}\n </Menu.Items>\n </Menu>\n </>\n );\n};\n\nconst Prompt = Object.assign(PromptComponent, {\n Select: AgentSelect,\n});\n\nexport { Prompt };\n"]}
|
|
@@ -34,13 +34,11 @@ const Component = () => {
|
|
|
34
34
|
const [selectedOption, setSelectedOption] = useState(options[0]);
|
|
35
35
|
const [prompt, setPrompt] = useState('');
|
|
36
36
|
const handleSubmitPrompt = () => {
|
|
37
|
-
setIsRunningPrompt(
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
setPrompt('');
|
|
41
|
-
}
|
|
37
|
+
setIsRunningPrompt(true);
|
|
38
|
+
alert(`You submitted the following prompt: ${prompt}`);
|
|
39
|
+
setPrompt('');
|
|
42
40
|
};
|
|
43
|
-
return (_jsx(Prompt, { isRunningPrompt: isRunningPrompt, value: prompt, onChange: (e) => setPrompt(e.target.value), onSubmitPrompt: handleSubmitPrompt, topContent: _jsxs(_Fragment, { children: [_jsx(FileTag, { isLoading: true, icon: _jsx(DocumentIconOutline, {}), fileName: "Science Fiction Bestsellers", fileType: "pdf", isRemovable: true, onClick: () => {
|
|
41
|
+
return (_jsx(Prompt, { isRunningPrompt: isRunningPrompt, value: prompt, onChange: (e) => setPrompt(e.target.value), onSubmitPrompt: handleSubmitPrompt, onCancelPrompt: () => setIsRunningPrompt(false), topContent: _jsxs(_Fragment, { children: [_jsx(FileTag, { isLoading: true, icon: _jsx(DocumentIconOutline, {}), fileName: "Science Fiction Bestsellers", fileType: "pdf", isRemovable: true, onClick: () => {
|
|
44
42
|
console.info('remove file');
|
|
45
43
|
} }), _jsx(ImageTag, { isLoading: true, src: "https://plus.unsplash.com/premium_photo-1676496046182-356a6a0ed002?q=80&w=2952&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D", alt: "Landscape image", fileName: "Landscape image", fileType: "jpg", isRemovable: true, onClick: () => {
|
|
46
44
|
console.info('remove image');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prompt-advanced.story.js","sourceRoot":"","sources":["../../../../../src/ai/prompt/stories/prompt-advanced.story.tsx"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,yCAAyC,CAAC;AAEjD,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAChE,OAAO,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAC9E,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAEjC,MAAM,SAAS,GAAG,GAAG,EAAE;IACrB,MAAM,CAAC,eAAe,EAAE,kBAAkB,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC9D,MAAM,OAAO,GAAqD;QAChE,EAAE,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,OAAO,EAAE;QACrC,EAAE,KAAK,EAAE,eAAe,EAAE,KAAK,EAAE,eAAe,EAAE;QAClD,EAAE,KAAK,EAAE,eAAe,EAAE,KAAK,EAAE,eAAe,EAAE;KACnD,CAAC;IACF,MAAM,CAAC,cAAc,EAAE,iBAAiB,CAAC,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;IACjE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC;IAEzC,MAAM,kBAAkB,GAAG,GAAG,EAAE;QAC9B,kBAAkB,CAAC,
|
|
1
|
+
{"version":3,"file":"prompt-advanced.story.js","sourceRoot":"","sources":["../../../../../src/ai/prompt/stories/prompt-advanced.story.tsx"],"names":[],"mappings":"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","sourcesContent":["/**\n *\n * Copyright (c) \"Neo4j\"\n * Neo4j Sweden AB [http://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Neo4j is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program. If not, see <http://www.gnu.org/licenses/>.\n */\n\nimport '@neo4j-ndl/base/lib/neo4j-ds-styles.css';\n\nimport { CleanIconButton } from '@neo4j-ndl/react';\nimport { FileTag, ImageTag, Prompt } from '@neo4j-ndl/react/ai';\nimport { DocumentIconOutline, PlusIconOutline } from '@neo4j-ndl/react/icons';\nimport { useState } from 'react';\n\nconst Component = () => {\n const [isRunningPrompt, setIsRunningPrompt] = useState(false);\n const options: Array<{ label: React.ReactNode; value: string }> = [\n { label: 'Neo4j AI', value: 'neo4j' },\n { label: 'Special Agent', value: 'special-agent' },\n { label: 'Another Agent', value: 'another-agent' },\n ];\n const [selectedOption, setSelectedOption] = useState(options[0]);\n const [prompt, setPrompt] = useState('');\n\n const handleSubmitPrompt = () => {\n setIsRunningPrompt(true);\n alert(`You submitted the following prompt: ${prompt}`);\n setPrompt('');\n };\n\n return (\n <Prompt\n isRunningPrompt={isRunningPrompt}\n value={prompt}\n onChange={(e) => setPrompt(e.target.value)}\n onSubmitPrompt={handleSubmitPrompt}\n onCancelPrompt={() => setIsRunningPrompt(false)}\n topContent={\n <>\n <FileTag\n isLoading={true}\n icon={<DocumentIconOutline />}\n fileName=\"Science Fiction Bestsellers\"\n fileType=\"pdf\"\n isRemovable={true}\n onClick={() => {\n console.info('remove file');\n }}\n />\n <ImageTag\n isLoading={true}\n src=\"https://plus.unsplash.com/premium_photo-1676496046182-356a6a0ed002?q=80&w=2952&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D\"\n alt=\"Landscape image\"\n fileName=\"Landscape image\"\n fileType=\"jpg\"\n isRemovable={true}\n onClick={() => {\n console.info('remove image');\n }}\n />\n <FileTag\n icon={<DocumentIconOutline />}\n fileName=\"Science Fiction Bestsellers\"\n fileType=\"pdf\"\n isRemovable={true}\n onClick={() => {\n console.info('remove file');\n }}\n />\n <ImageTag\n src=\"https://plus.unsplash.com/premium_photo-1676496046182-356a6a0ed002?q=80&w=2952&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D\"\n alt=\"Landscape image\"\n fileName=\"Landscape image\"\n fileType=\"jpg\"\n isRemovable={true}\n onClick={() => {\n console.info('remove image');\n }}\n />\n </>\n }\n bottomContent={\n <>\n <Prompt.Select\n value={selectedOption}\n options={options}\n onChange={setSelectedOption}\n />\n <CleanIconButton description=\"Add stuff\" size=\"small\">\n <PlusIconOutline />\n </CleanIconButton>\n </>\n }\n />\n );\n};\n\nexport default Component;\n"]}
|
|
@@ -26,13 +26,11 @@ const Component = () => {
|
|
|
26
26
|
const [prompt, setPrompt] = useState('');
|
|
27
27
|
const [isRunningPrompt, setIsRunningPrompt] = useState(false);
|
|
28
28
|
const handleSubmitPrompt = () => {
|
|
29
|
-
setIsRunningPrompt(
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
setPrompt('');
|
|
33
|
-
}
|
|
29
|
+
setIsRunningPrompt(true);
|
|
30
|
+
alert(`You submitted the following prompt: ${prompt}`);
|
|
31
|
+
setPrompt('');
|
|
34
32
|
};
|
|
35
|
-
return (_jsx(Prompt, { isRunningPrompt: isRunningPrompt, value: prompt, onChange: (e) => setPrompt(e.target.value), onSubmitPrompt: handleSubmitPrompt }));
|
|
33
|
+
return (_jsx(Prompt, { isRunningPrompt: isRunningPrompt, value: prompt, onChange: (e) => setPrompt(e.target.value), onSubmitPrompt: handleSubmitPrompt, onCancelPrompt: () => setIsRunningPrompt(false) }));
|
|
36
34
|
};
|
|
37
35
|
export default Component;
|
|
38
36
|
//# sourceMappingURL=prompt-default.story.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prompt-default.story.js","sourceRoot":"","sources":["../../../../../src/ai/prompt/stories/prompt-default.story.tsx"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,yCAAyC,CAAC;AAEjD,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAEjC,MAAM,SAAS,GAAG,GAAG,EAAE;IACrB,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC;IACzC,MAAM,CAAC,eAAe,EAAE,kBAAkB,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAE9D,MAAM,kBAAkB,GAAG,GAAG,EAAE;QAC9B,kBAAkB,CAAC,
|
|
1
|
+
{"version":3,"file":"prompt-default.story.js","sourceRoot":"","sources":["../../../../../src/ai/prompt/stories/prompt-default.story.tsx"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,yCAAyC,CAAC;AAEjD,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAEjC,MAAM,SAAS,GAAG,GAAG,EAAE;IACrB,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC;IACzC,MAAM,CAAC,eAAe,EAAE,kBAAkB,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAE9D,MAAM,kBAAkB,GAAG,GAAG,EAAE;QAC9B,kBAAkB,CAAC,IAAI,CAAC,CAAC;QACzB,KAAK,CAAC,uCAAuC,MAAM,EAAE,CAAC,CAAC;QACvD,SAAS,CAAC,EAAE,CAAC,CAAC;IAChB,CAAC,CAAC;IAEF,OAAO,CACL,KAAC,MAAM,IACL,eAAe,EAAE,eAAe,EAChC,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,CAAC,CAAyC,EAAE,EAAE,CACtD,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAE3B,cAAc,EAAE,kBAAkB,EAClC,cAAc,EAAE,GAAG,EAAE,CAAC,kBAAkB,CAAC,KAAK,CAAC,GAC/C,CACH,CAAC;AACJ,CAAC,CAAC;AAEF,eAAe,SAAS,CAAC","sourcesContent":["/**\n *\n * Copyright (c) \"Neo4j\"\n * Neo4j Sweden AB [http://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Neo4j is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program. If not, see <http://www.gnu.org/licenses/>.\n */\n\nimport '@neo4j-ndl/base/lib/neo4j-ds-styles.css';\n\nimport { Prompt } from '@neo4j-ndl/react/ai';\nimport { useState } from 'react';\n\nconst Component = () => {\n const [prompt, setPrompt] = useState('');\n const [isRunningPrompt, setIsRunningPrompt] = useState(false);\n\n const handleSubmitPrompt = () => {\n setIsRunningPrompt(true);\n alert(`You submitted the following prompt: ${prompt}`);\n setPrompt('');\n };\n\n return (\n <Prompt\n isRunningPrompt={isRunningPrompt}\n value={prompt}\n onChange={(e: React.ChangeEvent<HTMLTextAreaElement>) =>\n setPrompt(e.target.value)\n }\n onSubmitPrompt={handleSubmitPrompt}\n onCancelPrompt={() => setIsRunningPrompt(false)}\n />\n );\n};\n\nexport default Component;\n"]}
|
|
@@ -64,28 +64,26 @@ export const Component = () => {
|
|
|
64
64
|
useEffect(() => {
|
|
65
65
|
scrollToBottom();
|
|
66
66
|
}, [messages, isThinking]);
|
|
67
|
-
const
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
if (intervalRef.current) {
|
|
74
|
-
clearInterval(intervalRef.current);
|
|
75
|
-
}
|
|
76
|
-
setIsThinking(false);
|
|
77
|
-
setIsStreaming(false);
|
|
78
|
-
// Mark the last message as done if stopped
|
|
79
|
-
setMessages((prev) => {
|
|
80
|
-
const newMessages = [...prev];
|
|
81
|
-
const lastMessage = newMessages[newMessages.length - 1];
|
|
82
|
-
if ((lastMessage === null || lastMessage === void 0 ? void 0 : lastMessage.role) === 'assistant') {
|
|
83
|
-
lastMessage.done = true;
|
|
84
|
-
}
|
|
85
|
-
return newMessages;
|
|
86
|
-
});
|
|
87
|
-
return;
|
|
67
|
+
const handleCancel = () => {
|
|
68
|
+
if (timeoutRef.current) {
|
|
69
|
+
clearTimeout(timeoutRef.current);
|
|
70
|
+
}
|
|
71
|
+
if (intervalRef.current) {
|
|
72
|
+
clearInterval(intervalRef.current);
|
|
88
73
|
}
|
|
74
|
+
setIsThinking(false);
|
|
75
|
+
setIsStreaming(false);
|
|
76
|
+
// Mark the last message as done if stopped
|
|
77
|
+
setMessages((prev) => {
|
|
78
|
+
const newMessages = [...prev];
|
|
79
|
+
const lastMessage = newMessages[newMessages.length - 1];
|
|
80
|
+
if ((lastMessage === null || lastMessage === void 0 ? void 0 : lastMessage.role) === 'assistant') {
|
|
81
|
+
lastMessage.done = true;
|
|
82
|
+
}
|
|
83
|
+
return newMessages;
|
|
84
|
+
});
|
|
85
|
+
};
|
|
86
|
+
const handleSend = (overridePrompt) => {
|
|
89
87
|
const textToSend = overridePrompt || prompt;
|
|
90
88
|
if (!textToSend.trim()) {
|
|
91
89
|
return;
|
|
@@ -152,7 +150,7 @@ export const Component = () => {
|
|
|
152
150
|
}, children: "Generate a report" })] }), _jsxs(Typography, { variant: "body-medium", children: ["You can also drag and drop files here, or", ' ', _jsx(TextLink, { as: "button", type: "internal-underline", children: "browse" }), ". Supports CVG, MOV, PDF"] })] }) })) : (_jsxs("div", { className: "n-flex n-flex-col n-gap-4 n-pb-4", children: [messages.map((msg, idx) => (_jsx("div", { className: `n-flex ${msg.role === 'user' ? 'n-justify-end' : 'n-justify-start'}`, children: msg.role === 'user' ? (_jsx("div", { className: "n-max-w-[85%]", children: _jsx(UserBubble, { avatarProps: {
|
|
153
151
|
name: 'NM',
|
|
154
152
|
type: 'letters',
|
|
155
|
-
}, children: msg.content }) })) : (_jsxs("div", { className: "n-w-full n-flex n-flex-col n-gap-2", children: [msg.thinkingTime !== undefined && (_jsx(Thinking, { isThinking: false, thinkingMs: msg.thinkingTime })), _jsxs("div", { className: "n-flex n-flex-col n-gap-2", children: [_jsx(Response, { children: msg.content }), msg.done === true && (_jsxs("div", { className: "n-flex n-flex-row n-gap-1.5", children: [_jsx(CleanIconButton, { size: "small", description: "Dislike", children: _jsx(HandThumbDownIconOutline, {}) }), _jsx(CleanIconButton, { size: "small", description: "Re-run", children: _jsx(ArrowPathIconOutline, {}) }), _jsx(CleanIconButton, { size: "small", description: "Copy", children: _jsx(Square2StackIconOutline, {}) })] }))] })] })) }, idx))), isThinking && _jsx(Thinking, { isThinking: true }), _jsx("div", { ref: messagesEndRef })] })) }), _jsx("div", { className: "n-px-4 n-pt-4 n-pb-1 n-mt-auto", children: _jsx(Prompt, { value: prompt, onChange: (e) => setPrompt(e.target.value), onSubmitPrompt: () => handleSend(), isRunningPrompt: isThinking || isStreaming, isSubmitDisabled: prompt.length === 0 && !(isThinking || isStreaming), bottomContent: _jsx(CleanIconButton, { description: "Add files", size: "small", children: _jsx(PlusIconOutline, {}) }) }) })] }) }));
|
|
153
|
+
}, children: msg.content }) })) : (_jsxs("div", { className: "n-w-full n-flex n-flex-col n-gap-2", children: [msg.thinkingTime !== undefined && (_jsx(Thinking, { isThinking: false, thinkingMs: msg.thinkingTime })), _jsxs("div", { className: "n-flex n-flex-col n-gap-2", children: [_jsx(Response, { children: msg.content }), msg.done === true && (_jsxs("div", { className: "n-flex n-flex-row n-gap-1.5", children: [_jsx(CleanIconButton, { size: "small", description: "Dislike", children: _jsx(HandThumbDownIconOutline, {}) }), _jsx(CleanIconButton, { size: "small", description: "Re-run", children: _jsx(ArrowPathIconOutline, {}) }), _jsx(CleanIconButton, { size: "small", description: "Copy", children: _jsx(Square2StackIconOutline, {}) })] }))] })] })) }, idx))), isThinking && _jsx(Thinking, { isThinking: true }), _jsx("div", { ref: messagesEndRef })] })) }), _jsx("div", { className: "n-px-4 n-pt-4 n-pb-1 n-mt-auto", children: _jsx(Prompt, { value: prompt, onChange: (e) => setPrompt(e.target.value), onSubmitPrompt: () => handleSend(), onCancelPrompt: handleCancel, isRunningPrompt: isThinking || isStreaming, isSubmitDisabled: prompt.length === 0 && !(isThinking || isStreaming), bottomContent: _jsx(CleanIconButton, { description: "Add files", size: "small", children: _jsx(PlusIconOutline, {}) }) }) })] }) }));
|
|
156
154
|
};
|
|
157
155
|
export default Component;
|
|
158
156
|
//# sourceMappingURL=response-full-example.story.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"response-full-example.story.js","sourceRoot":"","sources":["../../../../../src/ai/response/stories/response-full-example.story.tsx"],"names":[],"mappings":"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","sourcesContent":["/**\n *\n * Copyright (c) \"Neo4j\"\n * Neo4j Sweden AB [http://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Neo4j is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program. If not, see <http://www.gnu.org/licenses/>.\n */\nimport { CleanIconButton, TextLink, Typography } from '@neo4j-ndl/react';\nimport {\n Prompt,\n Response,\n Suggestion,\n Thinking,\n UserBubble,\n} from '@neo4j-ndl/react/ai';\nimport {\n ArrowPathIconOutline,\n Cog6ToothIconOutline,\n HandThumbDownIconOutline,\n PlusIconOutline,\n Square2StackIconOutline,\n XMarkIconOutline,\n} from '@neo4j-ndl/react/icons';\nimport { useEffect, useRef, useState } from 'react';\n\nconst FAKE_RESPONSES = [\n `Here is a simple response with some **bold text** and *italics*.`,\n `Here is a list of items:\n- Item 1\n- Item 2\n- Item 3`,\n `Here is a code block example:\n\n\\`\\`\\`typescript\nconst greeting = \"Hello World\";\nconsole.log(greeting);\n\\`\\`\\`\n`,\n `# Heading 1\n## Heading 2\n### Heading 3\n\nSome text under headings.`,\n `You can also use tables:\n\n| Header 1 | Header 2 |\n|Data 1|Data 2|\n|Data 3|Data 4|\n`,\n];\n\nexport const Component = () => {\n const [messages, setMessages] = useState<\n {\n role: 'user' | 'assistant';\n content: string;\n thinkingTime?: number;\n done?: boolean;\n }[]\n >([]);\n const [prompt, setPrompt] = useState('');\n const [isThinking, setIsThinking] = useState(false);\n const [isStreaming, setIsStreaming] = useState(false);\n const [responseIndex, setResponseIndex] = useState(0);\n const messagesEndRef = useRef<HTMLDivElement>(null);\n const timeoutRef = useRef<NodeJS.Timeout | null>(null);\n const intervalRef = useRef<NodeJS.Timeout | null>(null);\n\n const scrollToBottom = () => {\n messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });\n };\n\n useEffect(() => {\n scrollToBottom();\n }, [messages, isThinking]);\n\n const handleSend = (overridePrompt?: string) => {\n // Handle Stop\n if (isThinking || isStreaming) {\n if (timeoutRef.current) {\n clearTimeout(timeoutRef.current);\n }\n if (intervalRef.current) {\n clearInterval(intervalRef.current);\n }\n setIsThinking(false);\n setIsStreaming(false);\n\n // Mark the last message as done if stopped\n setMessages((prev) => {\n const newMessages = [...prev];\n const lastMessage = newMessages[newMessages.length - 1];\n if (lastMessage?.role === 'assistant') {\n lastMessage.done = true;\n }\n return newMessages;\n });\n return;\n }\n\n const textToSend = overridePrompt || prompt;\n\n if (!textToSend.trim()) {\n return;\n }\n\n setMessages((prev) => [...prev, { content: textToSend, role: 'user' }]);\n setPrompt('');\n setIsThinking(true);\n const startTime = Date.now();\n\n // Simulate network delay (thinking time)\n timeoutRef.current = setTimeout(() => {\n const endTime = Date.now();\n const thinkingTime = endTime - startTime;\n setIsThinking(false);\n setIsStreaming(true);\n\n const responseText = FAKE_RESPONSES[responseIndex];\n setResponseIndex((prev) => (prev + 1) % FAKE_RESPONSES.length);\n\n let currentText = '';\n setMessages((prev) => [\n ...prev,\n { content: '', done: false, role: 'assistant', thinkingTime },\n ]);\n\n // Simulate streaming\n intervalRef.current = setInterval(() => {\n if (currentText.length < responseText.length) {\n // Add a few characters at a time to simulate chunks\n // Ensure we don't split newlines incorrectly if that's an issue,\n // but simple slicing should be fine as long as the source has \\n.\n const chunk = responseText.slice(\n currentText.length,\n currentText.length + 2,\n );\n currentText += chunk;\n\n setMessages((prev) => {\n const newMessages = [...prev];\n const lastMessage = newMessages[newMessages.length - 1];\n if (lastMessage.role === 'assistant') {\n lastMessage.content = currentText;\n }\n return newMessages;\n });\n } else {\n if (intervalRef.current) {\n clearInterval(intervalRef.current);\n }\n setIsStreaming(false);\n setMessages((prev) => {\n const newMessages = [...prev];\n const lastMessage = newMessages[newMessages.length - 1];\n if (lastMessage.role === 'assistant') {\n lastMessage.done = true;\n }\n return newMessages;\n });\n }\n }, 50);\n }, 2000);\n };\n\n return (\n <section className=\"n-h-screen\">\n <div className=\"n-w-[440px] n-h-full n-flex n-flex-col n-bg-neutral-bg-weak\">\n <div className=\"n-flex n-flex-row n-border-b n-border-neutral-border-weak n-p-3\">\n <div className=\"n-ml-auto\">\n <CleanIconButton description=\"settings\" tooltipProps={{}}>\n <Cog6ToothIconOutline />\n </CleanIconButton>\n <CleanIconButton description=\"close\">\n <XMarkIconOutline />\n </CleanIconButton>\n </div>\n </div>\n <div className=\"n-p-4 n-flex n-flex-col n-grow n-overflow-y-auto\">\n {messages.length === 0 ? (\n <div className=\"n-flex n-flex-col \">\n <div className=\"n-flex n-flex-col n-gap-12\">\n <Typography variant=\"display\">\n Hi [User], how can I help you today?\n </Typography>\n <div className=\"n-flex n-flex-col n-gap-4\">\n <Typography variant=\"body-medium\">Suggestions</Typography>\n <Suggestion\n isPrimary\n onClick={() => {\n handleSend('I want to import data');\n }}\n >\n I want to import data\n </Suggestion>\n <Suggestion\n onClick={() => {\n handleSend('Create an AI agent');\n }}\n >\n Create an AI agent\n </Suggestion>\n <Suggestion\n onClick={() => {\n handleSend('Invite project members');\n }}\n >\n Invite project members\n </Suggestion>\n <Suggestion\n onClick={() => {\n handleSend('Generate a report');\n }}\n >\n Generate a report\n </Suggestion>\n </div>\n <Typography variant=\"body-medium\">\n You can also drag and drop files here, or{' '}\n <TextLink as=\"button\" type=\"internal-underline\">\n browse\n </TextLink>\n . Supports CVG, MOV, PDF\n </Typography>\n </div>\n </div>\n ) : (\n <div className=\"n-flex n-flex-col n-gap-4 n-pb-4\">\n {messages.map((msg, idx) => (\n <div\n key={idx}\n className={`n-flex ${\n msg.role === 'user' ? 'n-justify-end' : 'n-justify-start'\n }`}\n >\n {msg.role === 'user' ? (\n <div className=\"n-max-w-[85%]\">\n <UserBubble\n avatarProps={{\n name: 'NM',\n type: 'letters',\n }}\n >\n {msg.content}\n </UserBubble>\n </div>\n ) : (\n <div className=\"n-w-full n-flex n-flex-col n-gap-2\">\n {msg.thinkingTime !== undefined && (\n <Thinking\n isThinking={false}\n thinkingMs={msg.thinkingTime}\n />\n )}\n <div className=\"n-flex n-flex-col n-gap-2\">\n <Response>{msg.content}</Response>\n\n {msg.done === true && (\n <div className=\"n-flex n-flex-row n-gap-1.5\">\n <CleanIconButton size=\"small\" description=\"Dislike\">\n <HandThumbDownIconOutline />\n </CleanIconButton>\n <CleanIconButton size=\"small\" description=\"Re-run\">\n <ArrowPathIconOutline />\n </CleanIconButton>\n <CleanIconButton size=\"small\" description=\"Copy\">\n <Square2StackIconOutline />\n </CleanIconButton>\n </div>\n )}\n </div>\n </div>\n )}\n </div>\n ))}\n {isThinking && <Thinking isThinking={true} />}\n <div ref={messagesEndRef} />\n </div>\n )}\n </div>\n <div className=\"n-px-4 n-pt-4 n-pb-1 n-mt-auto\">\n <Prompt\n value={prompt}\n onChange={(e) => setPrompt(e.target.value)}\n onSubmitPrompt={() => handleSend()}\n isRunningPrompt={isThinking || isStreaming}\n isSubmitDisabled={\n prompt.length === 0 && !(isThinking || isStreaming)\n }\n bottomContent={\n <CleanIconButton description=\"Add files\" size=\"small\">\n <PlusIconOutline />\n </CleanIconButton>\n }\n />\n </div>\n </div>\n </section>\n );\n};\n\nexport default Component;\n"]}
|
|
1
|
+
{"version":3,"file":"response-full-example.story.js","sourceRoot":"","sources":["../../../../../src/ai/response/stories/response-full-example.story.tsx"],"names":[],"mappings":"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","sourcesContent":["/**\n *\n * Copyright (c) \"Neo4j\"\n * Neo4j Sweden AB [http://neo4j.com]\n *\n * This file is part of Neo4j.\n *\n * Neo4j is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program. If not, see <http://www.gnu.org/licenses/>.\n */\nimport { CleanIconButton, TextLink, Typography } from '@neo4j-ndl/react';\nimport {\n Prompt,\n Response,\n Suggestion,\n Thinking,\n UserBubble,\n} from '@neo4j-ndl/react/ai';\nimport {\n ArrowPathIconOutline,\n Cog6ToothIconOutline,\n HandThumbDownIconOutline,\n PlusIconOutline,\n Square2StackIconOutline,\n XMarkIconOutline,\n} from '@neo4j-ndl/react/icons';\nimport { useEffect, useRef, useState } from 'react';\n\nconst FAKE_RESPONSES = [\n `Here is a simple response with some **bold text** and *italics*.`,\n `Here is a list of items:\n- Item 1\n- Item 2\n- Item 3`,\n `Here is a code block example:\n\n\\`\\`\\`typescript\nconst greeting = \"Hello World\";\nconsole.log(greeting);\n\\`\\`\\`\n`,\n `# Heading 1\n## Heading 2\n### Heading 3\n\nSome text under headings.`,\n `You can also use tables:\n\n| Header 1 | Header 2 |\n|Data 1|Data 2|\n|Data 3|Data 4|\n`,\n];\n\nexport const Component = () => {\n const [messages, setMessages] = useState<\n {\n role: 'user' | 'assistant';\n content: string;\n thinkingTime?: number;\n done?: boolean;\n }[]\n >([]);\n const [prompt, setPrompt] = useState('');\n const [isThinking, setIsThinking] = useState(false);\n const [isStreaming, setIsStreaming] = useState(false);\n const [responseIndex, setResponseIndex] = useState(0);\n const messagesEndRef = useRef<HTMLDivElement>(null);\n const timeoutRef = useRef<NodeJS.Timeout | null>(null);\n const intervalRef = useRef<NodeJS.Timeout | null>(null);\n\n const scrollToBottom = () => {\n messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });\n };\n\n useEffect(() => {\n scrollToBottom();\n }, [messages, isThinking]);\n\n const handleCancel = () => {\n if (timeoutRef.current) {\n clearTimeout(timeoutRef.current);\n }\n if (intervalRef.current) {\n clearInterval(intervalRef.current);\n }\n setIsThinking(false);\n setIsStreaming(false);\n\n // Mark the last message as done if stopped\n setMessages((prev) => {\n const newMessages = [...prev];\n const lastMessage = newMessages[newMessages.length - 1];\n if (lastMessage?.role === 'assistant') {\n lastMessage.done = true;\n }\n return newMessages;\n });\n };\n\n const handleSend = (overridePrompt?: string) => {\n const textToSend = overridePrompt || prompt;\n\n if (!textToSend.trim()) {\n return;\n }\n\n setMessages((prev) => [...prev, { content: textToSend, role: 'user' }]);\n setPrompt('');\n setIsThinking(true);\n const startTime = Date.now();\n\n // Simulate network delay (thinking time)\n timeoutRef.current = setTimeout(() => {\n const endTime = Date.now();\n const thinkingTime = endTime - startTime;\n setIsThinking(false);\n setIsStreaming(true);\n\n const responseText = FAKE_RESPONSES[responseIndex];\n setResponseIndex((prev) => (prev + 1) % FAKE_RESPONSES.length);\n\n let currentText = '';\n setMessages((prev) => [\n ...prev,\n { content: '', done: false, role: 'assistant', thinkingTime },\n ]);\n\n // Simulate streaming\n intervalRef.current = setInterval(() => {\n if (currentText.length < responseText.length) {\n // Add a few characters at a time to simulate chunks\n // Ensure we don't split newlines incorrectly if that's an issue,\n // but simple slicing should be fine as long as the source has \\n.\n const chunk = responseText.slice(\n currentText.length,\n currentText.length + 2,\n );\n currentText += chunk;\n\n setMessages((prev) => {\n const newMessages = [...prev];\n const lastMessage = newMessages[newMessages.length - 1];\n if (lastMessage.role === 'assistant') {\n lastMessage.content = currentText;\n }\n return newMessages;\n });\n } else {\n if (intervalRef.current) {\n clearInterval(intervalRef.current);\n }\n setIsStreaming(false);\n setMessages((prev) => {\n const newMessages = [...prev];\n const lastMessage = newMessages[newMessages.length - 1];\n if (lastMessage.role === 'assistant') {\n lastMessage.done = true;\n }\n return newMessages;\n });\n }\n }, 50);\n }, 2000);\n };\n\n return (\n <section className=\"n-h-screen\">\n <div className=\"n-w-[440px] n-h-full n-flex n-flex-col n-bg-neutral-bg-weak\">\n <div className=\"n-flex n-flex-row n-border-b n-border-neutral-border-weak n-p-3\">\n <div className=\"n-ml-auto\">\n <CleanIconButton description=\"settings\" tooltipProps={{}}>\n <Cog6ToothIconOutline />\n </CleanIconButton>\n <CleanIconButton description=\"close\">\n <XMarkIconOutline />\n </CleanIconButton>\n </div>\n </div>\n <div className=\"n-p-4 n-flex n-flex-col n-grow n-overflow-y-auto\">\n {messages.length === 0 ? (\n <div className=\"n-flex n-flex-col \">\n <div className=\"n-flex n-flex-col n-gap-12\">\n <Typography variant=\"display\">\n Hi [User], how can I help you today?\n </Typography>\n <div className=\"n-flex n-flex-col n-gap-4\">\n <Typography variant=\"body-medium\">Suggestions</Typography>\n <Suggestion\n isPrimary\n onClick={() => {\n handleSend('I want to import data');\n }}\n >\n I want to import data\n </Suggestion>\n <Suggestion\n onClick={() => {\n handleSend('Create an AI agent');\n }}\n >\n Create an AI agent\n </Suggestion>\n <Suggestion\n onClick={() => {\n handleSend('Invite project members');\n }}\n >\n Invite project members\n </Suggestion>\n <Suggestion\n onClick={() => {\n handleSend('Generate a report');\n }}\n >\n Generate a report\n </Suggestion>\n </div>\n <Typography variant=\"body-medium\">\n You can also drag and drop files here, or{' '}\n <TextLink as=\"button\" type=\"internal-underline\">\n browse\n </TextLink>\n . Supports CVG, MOV, PDF\n </Typography>\n </div>\n </div>\n ) : (\n <div className=\"n-flex n-flex-col n-gap-4 n-pb-4\">\n {messages.map((msg, idx) => (\n <div\n key={idx}\n className={`n-flex ${\n msg.role === 'user' ? 'n-justify-end' : 'n-justify-start'\n }`}\n >\n {msg.role === 'user' ? (\n <div className=\"n-max-w-[85%]\">\n <UserBubble\n avatarProps={{\n name: 'NM',\n type: 'letters',\n }}\n >\n {msg.content}\n </UserBubble>\n </div>\n ) : (\n <div className=\"n-w-full n-flex n-flex-col n-gap-2\">\n {msg.thinkingTime !== undefined && (\n <Thinking\n isThinking={false}\n thinkingMs={msg.thinkingTime}\n />\n )}\n <div className=\"n-flex n-flex-col n-gap-2\">\n <Response>{msg.content}</Response>\n\n {msg.done === true && (\n <div className=\"n-flex n-flex-row n-gap-1.5\">\n <CleanIconButton size=\"small\" description=\"Dislike\">\n <HandThumbDownIconOutline />\n </CleanIconButton>\n <CleanIconButton size=\"small\" description=\"Re-run\">\n <ArrowPathIconOutline />\n </CleanIconButton>\n <CleanIconButton size=\"small\" description=\"Copy\">\n <Square2StackIconOutline />\n </CleanIconButton>\n </div>\n )}\n </div>\n </div>\n )}\n </div>\n ))}\n {isThinking && <Thinking isThinking={true} />}\n <div ref={messagesEndRef} />\n </div>\n )}\n </div>\n <div className=\"n-px-4 n-pt-4 n-pb-1 n-mt-auto\">\n <Prompt\n value={prompt}\n onChange={(e) => setPrompt(e.target.value)}\n onSubmitPrompt={() => handleSend()}\n onCancelPrompt={handleCancel}\n isRunningPrompt={isThinking || isStreaming}\n isSubmitDisabled={\n prompt.length === 0 && !(isThinking || isStreaming)\n }\n bottomContent={\n <CleanIconButton description=\"Add files\" size=\"small\">\n <PlusIconOutline />\n </CleanIconButton>\n }\n />\n </div>\n </div>\n </section>\n );\n};\n\nexport default Component;\n"]}
|
|
@@ -32,6 +32,8 @@ type PromptProps = {
|
|
|
32
32
|
isRunningPrompt?: boolean;
|
|
33
33
|
/** Callback function called when the submit button is clicked */
|
|
34
34
|
onSubmitPrompt?: (e: React.KeyboardEvent<HTMLTextAreaElement> | React.MouseEvent<HTMLButtonElement, MouseEvent>) => void;
|
|
35
|
+
/** Callback function called when the cancel button is clicked */
|
|
36
|
+
onCancelPrompt?: (e: React.MouseEvent<HTMLButtonElement, MouseEvent>) => void;
|
|
35
37
|
/** Content to display above the textarea */
|
|
36
38
|
topContent?: React.ReactNode;
|
|
37
39
|
/** Content to display below the textarea */
|
|
@@ -55,7 +57,7 @@ type AgentSelectProps = {
|
|
|
55
57
|
value: string;
|
|
56
58
|
}) => void;
|
|
57
59
|
};
|
|
58
|
-
declare const Prompt: (({ value, onChange, maxRows, isRunningPrompt, onSubmitPrompt, isSubmitDisabled, topContent, bottomContent, disclaimer, className, style, htmlAttributes, ref, textareaProps, ...restProps }: CommonProps<"div", PromptProps>) => import("react/jsx-runtime").JSX.Element) & {
|
|
60
|
+
declare const Prompt: (({ value, onChange, maxRows, isRunningPrompt, onSubmitPrompt, onCancelPrompt, isSubmitDisabled, topContent, bottomContent, disclaimer, className, style, htmlAttributes, ref, textareaProps, ...restProps }: CommonProps<"div", PromptProps>) => import("react/jsx-runtime").JSX.Element) & {
|
|
59
61
|
Select: ({ value, options, onChange }: AgentSelectProps) => import("react/jsx-runtime").JSX.Element;
|
|
60
62
|
};
|
|
61
63
|
export { Prompt };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Prompt.d.ts","sourceRoot":"","sources":["../../../../src/ai/prompt/Prompt.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAgBH,OAAO,KAAK,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAEvE,KAAK,WAAW,GAAG;IACjB,sBAAsB;IACtB,KAAK,CAAC,EAAE,KAAK,CAAC,wBAAwB,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,CAAC;IAC5D,4DAA4D;IAC5D,QAAQ,CAAC,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC,WAAW,CAAC,mBAAmB,CAAC,KAAK,IAAI,CAAC;IAC/D,4CAA4C;IAC5C,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,wDAAwD;IACxD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,2EAA2E;IAC3E,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,iEAAiE;IACjE,cAAc,CAAC,EAAE,CACf,CAAC,EACG,KAAK,CAAC,aAAa,CAAC,mBAAmB,CAAC,GACxC,KAAK,CAAC,UAAU,CAAC,iBAAiB,EAAE,UAAU,CAAC,KAChD,IAAI,CAAC;IACV,4CAA4C;IAC5C,UAAU,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC7B,4CAA4C;IAC5C,aAAa,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAChC,gDAAgD;IAChD,UAAU,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC7B,qCAAqC;IACrC,aAAa,CAAC,EAAE,cAAc,CAAC,UAAU,CAAC,CAAC;CAC5C,CAAC;
|
|
1
|
+
{"version":3,"file":"Prompt.d.ts","sourceRoot":"","sources":["../../../../src/ai/prompt/Prompt.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAgBH,OAAO,KAAK,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAEvE,KAAK,WAAW,GAAG;IACjB,sBAAsB;IACtB,KAAK,CAAC,EAAE,KAAK,CAAC,wBAAwB,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,CAAC;IAC5D,4DAA4D;IAC5D,QAAQ,CAAC,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC,WAAW,CAAC,mBAAmB,CAAC,KAAK,IAAI,CAAC;IAC/D,4CAA4C;IAC5C,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,wDAAwD;IACxD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,2EAA2E;IAC3E,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,iEAAiE;IACjE,cAAc,CAAC,EAAE,CACf,CAAC,EACG,KAAK,CAAC,aAAa,CAAC,mBAAmB,CAAC,GACxC,KAAK,CAAC,UAAU,CAAC,iBAAiB,EAAE,UAAU,CAAC,KAChD,IAAI,CAAC;IACV,iEAAiE;IACjE,cAAc,CAAC,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC,UAAU,CAAC,iBAAiB,EAAE,UAAU,CAAC,KAAK,IAAI,CAAC;IAC9E,4CAA4C;IAC5C,UAAU,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC7B,4CAA4C;IAC5C,aAAa,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAChC,gDAAgD;IAChD,UAAU,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC7B,qCAAqC;IACrC,aAAa,CAAC,EAAE,cAAc,CAAC,UAAU,CAAC,CAAC;CAC5C,CAAC;AA+NF,KAAK,gBAAgB,GAAG;IACtB,KAAK,EAAE;QAAE,KAAK,EAAE,KAAK,CAAC,SAAS,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IACjD,OAAO,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,KAAK,CAAC,SAAS,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC1D,QAAQ,EAAE,CAAC,MAAM,EAAE;QAAE,KAAK,EAAE,KAAK,CAAC,SAAS,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;CACvE,CAAC;AAkDF,QAAA,MAAM,MAAM,gNA3PT,WAAW,CAAC,KAAK,EAAE,WAAW,CAAC;2CA2MsB,gBAAgB;CAkDtE,CAAC;AAEH,OAAO,EAAE,MAAM,EAAE,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prompt-advanced.story.d.ts","sourceRoot":"","sources":["../../../../../src/ai/prompt/stories/prompt-advanced.story.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,yCAAyC,CAAC;AAOjD,QAAA,MAAM,SAAS,+
|
|
1
|
+
{"version":3,"file":"prompt-advanced.story.d.ts","sourceRoot":"","sources":["../../../../../src/ai/prompt/stories/prompt-advanced.story.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,yCAAyC,CAAC;AAOjD,QAAA,MAAM,SAAS,+CAiFd,CAAC;AAEF,eAAe,SAAS,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prompt-default.story.d.ts","sourceRoot":"","sources":["../../../../../src/ai/prompt/stories/prompt-default.story.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,yCAAyC,CAAC;AAKjD,QAAA,MAAM,SAAS,+
|
|
1
|
+
{"version":3,"file":"prompt-default.story.d.ts","sourceRoot":"","sources":["../../../../../src/ai/prompt/stories/prompt-default.story.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,yCAAyC,CAAC;AAKjD,QAAA,MAAM,SAAS,+CAqBd,CAAC;AAEF,eAAe,SAAS,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"response-full-example.story.d.ts","sourceRoot":"","sources":["../../../../../src/ai/response/stories/response-full-example.story.tsx"],"names":[],"mappings":"AAgEA,eAAO,MAAM,SAAS,+
|
|
1
|
+
{"version":3,"file":"response-full-example.story.d.ts","sourceRoot":"","sources":["../../../../../src/ai/response/stories/response-full-example.story.tsx"],"names":[],"mappings":"AAgEA,eAAO,MAAM,SAAS,+CAuPrB,CAAC;AAEF,eAAe,SAAS,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@neo4j-ndl/react",
|
|
3
|
-
"version": "4.3.
|
|
3
|
+
"version": "4.3.4",
|
|
4
4
|
"sideEffects": false,
|
|
5
5
|
"description": "React implementation of Neo4j Design System",
|
|
6
6
|
"keywords": [
|
|
@@ -68,9 +68,7 @@
|
|
|
68
68
|
"@vitejs/plugin-react": "5.0.2",
|
|
69
69
|
"ajv": "8.17.1",
|
|
70
70
|
"chromatic": "13.3.0",
|
|
71
|
-
"happo
|
|
72
|
-
"happo-playwright": "4.0.3",
|
|
73
|
-
"happo.io": "13.0.0",
|
|
71
|
+
"happo": "6.2.0",
|
|
74
72
|
"jsdom": "26.1.0",
|
|
75
73
|
"leva": "0.10.0",
|
|
76
74
|
"react": "19.2.1",
|
|
@@ -86,7 +84,7 @@
|
|
|
86
84
|
"@tanstack/react-table": "8.21.3",
|
|
87
85
|
"react": ">=19.0.0",
|
|
88
86
|
"react-dom": ">=19.0.0",
|
|
89
|
-
"@neo4j-ndl/base": "^4.3.
|
|
87
|
+
"@neo4j-ndl/base": "^4.3.3"
|
|
90
88
|
},
|
|
91
89
|
"dependencies": {
|
|
92
90
|
"@dnd-kit/core": "6.3.1",
|