UNPKG

@neo4j-ndl/react

Version:

React implementation of Neo4j Design System

217 lines 13.8 kB
"use strict"; var __rest = (this && this.__rest) || function (s, e) { var t = {}; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p]; if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]]; } return t; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.Response = void 0; const jsx_runtime_1 = require("react/jsx-runtime"); /** * * Copyright (c) "Neo4j" * Neo4j Sweden AB [http://neo4j.com] * * This file is part of Neo4j. * * Neo4j is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ // oxlint-disable sort-keys const react_1 = require("@neo4j-ndl/react"); const classnames_1 = __importDefault(require("classnames")); const react_2 = require("react"); const streamdown_1 = require("streamdown"); const code_languages_1 = require("../../code-block/code-languages"); const code_preview_1 = require("../code-preview"); /** * The component is used to display the response from an LLM. * It handles markdown rendering and streaming. * * @alpha - Changes to this component may be breaking. */ const Response = (0, react_2.memo)((_a) => { var { className, children, isAnimating = false, ref, style, htmlAttributes } = _a, restProps = __rest(_a, ["className", "children", "isAnimating", "ref", "style", "htmlAttributes"]); // Use a ref to store the current markdown content so we can check for unclosed fences // without recreating the components object on every render const childrenRef = (0, react_2.useRef)(children); childrenRef.current = children; const components = (0, react_2.useMemo)(() => ({ // oxlint-disable-next-line no-unused-vars ol: (_a) => { var { node, children, className, ref: _ref } = _a, props = __rest(_a, ["node", "children", "className", "ref"]); return ((0, jsx_runtime_1.jsx)("ol", Object.assign({ className: className }, props, { children: children }))); }, // oxlint-disable-next-line no-unused-vars ul: (_a) => { var { node, children, className, ref: _ref } = _a, props = __rest(_a, ["node", "children", "className", "ref"]); return ((0, jsx_runtime_1.jsx)("ul", Object.assign({ className: (0, classnames_1.default)(className) }, props, { children: children }))); }, // oxlint-disable-next-line no-unused-vars li: (_a) => { var { node, children, className, ref: _ref } = _a, props = __rest(_a, ["node", "children", "className", "ref"]); return ((0, jsx_runtime_1.jsx)("li", Object.assign({ className: className }, props, { children: children }))); }, // oxlint-disable-next-line no-unused-vars hr: (_a) => { var { node, className, ref: _ref } = _a, props = __rest(_a, ["node", "className", "ref"]); return ((0, jsx_runtime_1.jsx)("hr", Object.assign({ className: (0, classnames_1.default)(className) }, props))); }, // oxlint-disable-next-line no-unused-vars strong: (_a) => { var { node: _node, children, className, style, ref: _ref } = _a, props = __rest(_a, ["node", "children", "className", "style", "ref"]); return ((0, jsx_runtime_1.jsx)(react_1.Typography, Object.assign({ as: "strong", variant: "body-medium", className: className, style: Object.assign(Object.assign({}, style), { fontWeight: 'bold' }) }, props, { children: children }))); }, // oxlint-disable-next-line no-unused-vars em: (_a) => { var { node, children, className, style, ref: _ref } = _a, props = __rest(_a, ["node", "children", "className", "style", "ref"]); return ((0, jsx_runtime_1.jsx)(react_1.Typography, Object.assign({ as: "em", variant: "body-medium", className: className, style: Object.assign(Object.assign({}, style), { fontStyle: 'italic' }) }, props, { children: children }))); }, // oxlint-disable-next-line no-unused-vars a: (_a) => { var { node, children, className, href } = _a, props = __rest(_a, ["node", "children", "className", "href"]); return ((0, jsx_runtime_1.jsx)(react_1.TextLink, { type: "internal-underline", className: className, href: href, htmlAttributes: props, children: children })); }, // oxlint-disable-next-line no-unused-vars h1: (_a) => { var { node, children, className } = _a, props = __rest(_a, ["node", "children", "className"]); return ((0, jsx_runtime_1.jsx)("h1", Object.assign({ className: className }, props, { children: children }))); }, // oxlint-disable-next-line no-unused-vars h2: (_a) => { var { node, children, className } = _a, props = __rest(_a, ["node", "children", "className"]); return ((0, jsx_runtime_1.jsx)("h2", Object.assign({ className: className }, props, { children: children }))); }, // oxlint-disable-next-line no-unused-vars h3: (_a) => { var { node, children, className } = _a, props = __rest(_a, ["node", "children", "className"]); return ((0, jsx_runtime_1.jsx)("h3", Object.assign({ className: className }, props, { children: children }))); }, // oxlint-disable-next-line no-unused-vars h4: (_a) => { var { node, children, className } = _a, props = __rest(_a, ["node", "children", "className"]); return ((0, jsx_runtime_1.jsx)("h4", Object.assign({ className: className }, props, { children: children }))); }, // oxlint-disable-next-line no-unused-vars h5: (_a) => { var { node, children, className } = _a, props = __rest(_a, ["node", "children", "className"]); return ((0, jsx_runtime_1.jsx)("h5", Object.assign({ className: className }, props, { children: children }))); }, // oxlint-disable-next-line no-unused-vars h6: (_a) => { var { node, children, className } = _a, props = __rest(_a, ["node", "children", "className"]); return ((0, jsx_runtime_1.jsx)("h6", Object.assign({ className: className }, props, { children: children }))); }, // oxlint-disable-next-line no-unused-vars table: (_a) => { var { node, children, className, ref: _ref } = _a, props = __rest(_a, ["node", "children", "className", "ref"]); return ((0, jsx_runtime_1.jsx)("div", { className: "ndl-ai-response-table-wrapper", children: (0, jsx_runtime_1.jsx)("table", Object.assign({ className: className }, props, { children: children })) })); }, // oxlint-disable-next-line no-unused-vars thead: (_a) => { var { node, children, className, ref: _ref } = _a, props = __rest(_a, ["node", "children", "className", "ref"]); return ((0, jsx_runtime_1.jsx)("thead", Object.assign({ className: className }, props, { children: children }))); }, // oxlint-disable-next-line no-unused-vars tbody: (_a) => { var { node, children, className, ref: _ref } = _a, props = __rest(_a, ["node", "children", "className", "ref"]); return ((0, jsx_runtime_1.jsx)("tbody", Object.assign({ className: className }, props, { children: children }))); }, // oxlint-disable-next-line no-unused-vars tr: (_a) => { var { node, children, className, ref: _ref } = _a, props = __rest(_a, ["node", "children", "className", "ref"]); return ((0, jsx_runtime_1.jsx)("tr", Object.assign({ className: className }, props, { children: children }))); }, // oxlint-disable-next-line no-unused-vars th: (_a) => { var { node, children, className, ref: _ref } = _a, props = __rest(_a, ["node", "children", "className", "ref"]); return ((0, jsx_runtime_1.jsx)("th", Object.assign({ className: className }, props, { children: children }))); }, // oxlint-disable-next-line no-unused-vars td: (_a) => { var { node, children, className, ref: _ref } = _a, props = __rest(_a, ["node", "children", "className", "ref"]); return ((0, jsx_runtime_1.jsx)("td", Object.assign({ className: className }, props, { children: children }))); }, // oxlint-disable-next-line no-unused-vars blockquote: (_a) => { var { node, children, className, ref: _ref } = _a, props = __rest(_a, ["node", "children", "className", "ref"]); return ((0, jsx_runtime_1.jsx)("blockquote", Object.assign({ className: (0, classnames_1.default)(className) }, props, { children: children }))); }, code: (_a) => { var _b, _c, _d, _e; var { node, className, children: codeChildren } = _a, props = __rest(_a, ["node", "className", "children"]); const isInline = ((_b = node === null || node === void 0 ? void 0 : node.position) === null || _b === void 0 ? void 0 : _b.start.line) === ((_c = node === null || node === void 0 ? void 0 : node.position) === null || _c === void 0 ? void 0 : _c.end.line); const nodeClassNamesRaw = (_d = node === null || node === void 0 ? void 0 : node.properties) === null || _d === void 0 ? void 0 : _d.className; const nodeClassNamesArray = []; if (typeof nodeClassNamesRaw === 'string') { nodeClassNamesArray.push.apply(nodeClassNamesArray, nodeClassNamesRaw.split(' ')); } else if (Array.isArray(nodeClassNamesRaw)) { nodeClassNamesArray.push.apply(nodeClassNamesArray, nodeClassNamesRaw); } let language = 'text'; const rawLanguage = nodeClassNamesArray.find((string) => string.startsWith('language-')); if (rawLanguage !== undefined) { language = (_e = rawLanguage.replace('language-', '')) !== null && _e !== void 0 ? _e : 'text'; } language = code_languages_1.Languages.includes(language) ? language : 'text'; if (isInline) { return ((0, jsx_runtime_1.jsx)(react_1.Code, { isRunnable: false, className: className, htmlAttributes: props, children: codeChildren })); } if (typeof codeChildren === 'string') { // Check if code fences are balanced in the markdown // If there are an odd number of fences, it means there's an unclosed code block const fenceMatches = childrenRef.current.match(/```/g); const fenceCount = fenceMatches ? fenceMatches.length : 0; const hasUnclosedFence = fenceCount % 2 !== 0; // Show loading state when there's an unclosed fence (code block is streaming) const isCodeBlockLoading = hasUnclosedFence; return ((0, jsx_runtime_1.jsx)(code_preview_1.CodePreview, { code: codeChildren, isLoading: isCodeBlockLoading, language: language, className: className, htmlAttributes: Object.assign({}, props) }, props.key)); } else { return (0, jsx_runtime_1.jsx)("code", { className: className, children: codeChildren }); } }, // oxlint-disable-next-line no-unused-vars pre: (_a) => { var { node, className, children, ref: _ref } = _a, props = __rest(_a, ["node", "className", "children", "ref"]); return ((0, jsx_runtime_1.jsx)("pre", Object.assign({ className: className }, props, { children: children }))); }, // oxlint-disable-next-line no-unused-vars p: (_a) => { var { node, children, className, ref: _ref } = _a, props = __rest(_a, ["node", "children", "className", "ref"]); return ((0, jsx_runtime_1.jsx)(react_1.Typography, Object.assign({ as: "p", variant: "body-medium", className: (0, classnames_1.default)(className) }, props, { children: children }))); }, // oxlint-disable-next-line no-unused-vars img: (_a) => { var { node, className, src, alt, ref: _ref } = _a, props = __rest(_a, ["node", "className", "src", "alt", "ref"]); return ((0, jsx_runtime_1.jsx)("img", Object.assign({ className: (0, classnames_1.default)(className), src: src, alt: alt }, props))); }, }), []); return ((0, jsx_runtime_1.jsx)("div", Object.assign({ ref: ref, style: style, className: (0, classnames_1.default)('ndl-ai-response', className) }, restProps, htmlAttributes, { children: (0, jsx_runtime_1.jsx)(streamdown_1.Streamdown, { isAnimating: isAnimating, parseIncompleteMarkdown: isAnimating, components: components, children: children }) }))); }, (prevProps, nextProps) => prevProps.children === nextProps.children); exports.Response = Response; Response.displayName = 'Response'; //# sourceMappingURL=Response.js.map