@neo4j-ndl/react 4.18.7 → 4.18.8

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.
@@ -38,6 +38,9 @@ const jsx_runtime_1 = require("react/jsx-runtime");
38
38
  */
39
39
  const react_1 = require("@neo4j-ndl/react");
40
40
  const classnames_1 = __importDefault(require("classnames"));
41
+ const react_2 = require("react");
42
+ const ChevronDownIconOutline_1 = require("../../icons/generated/heroIcons/ChevronDownIconOutline");
43
+ const ChevronUpIconOutline_1 = require("../../icons/generated/heroIcons/ChevronUpIconOutline");
41
44
  /**
42
45
  * The component is used to display the user's message in a chat.
43
46
  * It has an avatar to represent the user and a trailing element to display potential additional actions.
@@ -45,9 +48,43 @@ const classnames_1 = __importDefault(require("classnames"));
45
48
  * @alpha - Changes to this component may be breaking.
46
49
  */
47
50
  const UserBubbleComponent = (_a) => {
48
- var { avatarProps, trailingElement, children, className, style, htmlAttributes, ref } = _a, restProps = __rest(_a, ["avatarProps", "trailingElement", "children", "className", "style", "htmlAttributes", "ref"]);
51
+ var { avatarProps, trailingElement, children, maxLines = 4, className, style, htmlAttributes, ref } = _a, restProps = __rest(_a, ["avatarProps", "trailingElement", "children", "maxLines", "className", "style", "htmlAttributes", "ref"]);
49
52
  const classes = (0, classnames_1.default)('ndl-ai-user-bubble', className);
50
- return ((0, jsx_runtime_1.jsxs)("div", Object.assign({ ref: ref, className: classes, style: style }, restProps, htmlAttributes, { children: [(0, jsx_runtime_1.jsx)(react_1.Avatar, Object.assign({ type: "image" }, avatarProps, { size: "small", shape: "circle", className: (0, classnames_1.default)('ndl-ai-user-bubble-avatar', avatarProps === null || avatarProps === void 0 ? void 0 : avatarProps.className) })), (0, jsx_runtime_1.jsx)(react_1.Typography, { variant: "body-medium", className: "ndl-ai-user-bubble-content", children: children }), (0, jsx_runtime_1.jsx)("div", { className: "ndl-ai-user-bubble-trailing", children: trailingElement })] })));
53
+ const contentRef = (0, react_2.useRef)(null);
54
+ const [isExpanded, setIsExpanded] = (0, react_2.useState)(false);
55
+ const [hasOverflow, setHasOverflow] = (0, react_2.useState)(false);
56
+ const isCollapseEnabled = maxLines !== null;
57
+ (0, react_2.useLayoutEffect)(() => {
58
+ const element = contentRef.current;
59
+ if (element === null || maxLines === null) {
60
+ setHasOverflow(false);
61
+ return;
62
+ }
63
+ const checkOverflow = () => {
64
+ const lineHeight = Number.parseFloat(window.getComputedStyle(element).lineHeight);
65
+ if (!Number.isFinite(lineHeight)) {
66
+ return;
67
+ }
68
+ setHasOverflow(element.scrollHeight > lineHeight * maxLines + 1);
69
+ };
70
+ checkOverflow();
71
+ const resizeObserver = new ResizeObserver(checkOverflow);
72
+ resizeObserver.observe(element);
73
+ return () => {
74
+ resizeObserver.disconnect();
75
+ };
76
+ }, [children, isExpanded, maxLines]);
77
+ const expandButton = hasOverflow ? ((0, jsx_runtime_1.jsxs)("div", { className: "ndl-ai-user-bubble-expand-wrap", children: [(0, jsx_runtime_1.jsx)(react_1.CleanIconButton, { className: "ndl-ai-user-bubble-expand", size: "small", onClick: () => setIsExpanded((expanded) => !expanded), description: isExpanded ? 'Show less' : 'Show more', htmlAttributes: {
78
+ 'aria-expanded': isExpanded,
79
+ type: 'button',
80
+ }, children: isExpanded ? (0, jsx_runtime_1.jsx)(ChevronUpIconOutline_1.ChevronUpIconOutline, {}) : (0, jsx_runtime_1.jsx)(ChevronDownIconOutline_1.ChevronDownIconOutline, {}) }), (0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("div", { className: "ndl-ai-user-bubble-expand-blur", "aria-hidden": "true" }), (0, jsx_runtime_1.jsx)("div", { className: "ndl-ai-user-bubble-expand-fill", "aria-hidden": "true" })] })] })) : null;
81
+ return ((0, jsx_runtime_1.jsxs)("div", Object.assign({ ref: ref, className: classes, style: style }, restProps, htmlAttributes, { children: [avatarProps && ((0, jsx_runtime_1.jsx)(react_1.Avatar, Object.assign({ type: "image" }, avatarProps, { size: "small", shape: "circle", className: (0, classnames_1.default)('ndl-ai-user-bubble-avatar', avatarProps === null || avatarProps === void 0 ? void 0 : avatarProps.className) }))), (0, jsx_runtime_1.jsxs)("div", { className: "ndl-ai-user-bubble-main", children: [(0, jsx_runtime_1.jsxs)(react_1.Typography, { as: "div", variant: "body-medium", ref: contentRef, className: (0, classnames_1.default)('ndl-ai-user-bubble-content', {
82
+ 'ndl-ai-user-bubble-content-clamped': isCollapseEnabled && !isExpanded,
83
+ }), style: isCollapseEnabled
84
+ ? {
85
+ '--ndl-ai-user-bubble-collapsed-lines': maxLines,
86
+ }
87
+ : undefined, children: [children, hasOverflow && isExpanded && ((0, jsx_runtime_1.jsx)("span", { className: "ndl-ai-user-bubble-expand-spacer", "aria-hidden": "true" }))] }), hasOverflow && ((0, jsx_runtime_1.jsx)("div", { className: "ndl-ai-user-bubble-toggle", children: expandButton }))] }), (0, jsx_runtime_1.jsx)("div", { className: "ndl-ai-user-bubble-trailing", children: trailingElement })] })));
51
88
  };
52
89
  exports.UserBubble = UserBubbleComponent;
53
90
  //# sourceMappingURL=UserBubble.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"UserBubble.js","sourceRoot":"","sources":["../../../../src/ai/user-bubble/UserBubble.tsx"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,4CAAsD;AACtD,4DAAoC;AAapC;;;;;GAKG;AACH,MAAM,mBAAmB,GAAG,CAAC,EASS,EAAE,EAAE;QATb,EAC3B,WAAW,EACX,eAAe,EACf,QAAQ,EACR,SAAS,EACT,KAAK,EACL,cAAc,EACd,GAAG,OAEiC,EADjC,SAAS,cARe,6FAS5B,CADa;IAEZ,MAAM,OAAO,GAAG,IAAA,oBAAU,EAAC,oBAAoB,EAAE,SAAS,CAAC,CAAC;IAE5D,OAAO,CACL,+CACE,GAAG,EAAE,GAAG,EACR,SAAS,EAAE,OAAO,EAClB,KAAK,EAAE,KAAK,IACR,SAAS,EACT,cAAc,eAElB,uBAAC,cAAM,kBACL,IAAI,EAAC,OAAO,IACR,WAAW,IACf,IAAI,EAAC,OAAO,EACZ,KAAK,EAAC,QAAQ,EACd,SAAS,EAAE,IAAA,oBAAU,EACnB,2BAA2B,EAC3B,WAAW,aAAX,WAAW,uBAAX,WAAW,CAAE,SAAS,CACvB,IACD,EACF,uBAAC,kBAAU,IAAC,OAAO,EAAC,aAAa,EAAC,SAAS,EAAC,4BAA4B,YACrE,QAAQ,GACE,EACb,gCAAK,SAAS,EAAC,6BAA6B,YAAE,eAAe,GAAO,KAChE,CACP,CAAC;AACJ,CAAC,CAAC;AAE8B,yCAAU","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 { Avatar, Typography } from '@neo4j-ndl/react';\nimport classNames from 'classnames';\n\nimport type { CommonProps } from '../../_common/types';\n\ntype UserBubbleProps = {\n /** The content of the user bubble */\n children?: React.ReactNode;\n /** The props for the avatar */\n avatarProps?: React.ComponentProps<typeof Avatar>;\n /** The element to display after the content. Could be a CleanIconButton to edit the user bubble. */\n trailingElement?: React.ReactNode;\n};\n\n/**\n * The component is used to display the user's message in a chat.\n * It has an avatar to represent the user and a trailing element to display potential additional actions.\n *\n * @alpha - Changes to this component may be breaking.\n */\nconst UserBubbleComponent = ({\n avatarProps,\n trailingElement,\n children,\n className,\n style,\n htmlAttributes,\n ref,\n ...restProps\n}: CommonProps<'div', UserBubbleProps>) => {\n const classes = classNames('ndl-ai-user-bubble', className);\n\n return (\n <div\n ref={ref}\n className={classes}\n style={style}\n {...restProps}\n {...htmlAttributes}\n >\n <Avatar\n type=\"image\"\n {...avatarProps}\n size=\"small\"\n shape=\"circle\"\n className={classNames(\n 'ndl-ai-user-bubble-avatar',\n avatarProps?.className,\n )}\n />\n <Typography variant=\"body-medium\" className=\"ndl-ai-user-bubble-content\">\n {children}\n </Typography>\n <div className=\"ndl-ai-user-bubble-trailing\">{trailingElement}</div>\n </div>\n );\n};\n\nexport { UserBubbleComponent as UserBubble };\n"]}
1
+ {"version":3,"file":"UserBubble.js","sourceRoot":"","sources":["../../../../src/ai/user-bubble/UserBubble.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 { Avatar, CleanIconButton, Typography } from '@neo4j-ndl/react';\nimport classNames from 'classnames';\nimport { useLayoutEffect, useRef, useState } from 'react';\n\nimport type { CommonProps } from '../../_common/types';\nimport { ChevronDownIconOutline } from '../../icons/generated/heroIcons/ChevronDownIconOutline';\nimport { ChevronUpIconOutline } from '../../icons/generated/heroIcons/ChevronUpIconOutline';\n\ntype UserBubbleProps = {\n /** The content of the user bubble */\n children?: React.ReactNode;\n /** The props for the avatar */\n avatarProps?: React.ComponentProps<typeof Avatar>;\n /** The element to display after the content. Could be a CleanIconButton to edit the user bubble. */\n trailingElement?: React.ReactNode;\n /**\n * Maximum number of lines visible before the message is collapsed.\n * Set to `null` to always show the full message.\n * @default 4\n */\n maxLines?: number | null;\n};\n\n/**\n * The component is used to display the user's message in a chat.\n * It has an avatar to represent the user and a trailing element to display potential additional actions.\n *\n * @alpha - Changes to this component may be breaking.\n */\nconst UserBubbleComponent = ({\n avatarProps,\n trailingElement,\n children,\n maxLines = 4,\n className,\n style,\n htmlAttributes,\n ref,\n ...restProps\n}: CommonProps<'div', UserBubbleProps>) => {\n const classes = classNames('ndl-ai-user-bubble', className);\n const contentRef = useRef<HTMLDivElement>(null);\n const [isExpanded, setIsExpanded] = useState(false);\n const [hasOverflow, setHasOverflow] = useState(false);\n const isCollapseEnabled = maxLines !== null;\n\n useLayoutEffect(() => {\n const element = contentRef.current;\n if (element === null || maxLines === null) {\n setHasOverflow(false);\n return;\n }\n\n const checkOverflow = () => {\n const lineHeight = Number.parseFloat(\n window.getComputedStyle(element).lineHeight,\n );\n if (!Number.isFinite(lineHeight)) {\n return;\n }\n\n setHasOverflow(element.scrollHeight > lineHeight * maxLines + 1);\n };\n\n checkOverflow();\n\n const resizeObserver = new ResizeObserver(checkOverflow);\n resizeObserver.observe(element);\n\n return () => {\n resizeObserver.disconnect();\n };\n }, [children, isExpanded, maxLines]);\n\n const expandButton = hasOverflow ? (\n <div className=\"ndl-ai-user-bubble-expand-wrap\">\n <CleanIconButton\n className=\"ndl-ai-user-bubble-expand\"\n size=\"small\"\n onClick={() => setIsExpanded((expanded) => !expanded)}\n description={isExpanded ? 'Show less' : 'Show more'}\n htmlAttributes={{\n 'aria-expanded': isExpanded,\n type: 'button',\n }}\n >\n {isExpanded ? <ChevronUpIconOutline /> : <ChevronDownIconOutline />}\n </CleanIconButton>\n <>\n <div className=\"ndl-ai-user-bubble-expand-blur\" aria-hidden=\"true\" />\n <div className=\"ndl-ai-user-bubble-expand-fill\" aria-hidden=\"true\" />\n </>\n </div>\n ) : null;\n\n return (\n <div\n ref={ref}\n className={classes}\n style={style}\n {...restProps}\n {...htmlAttributes}\n >\n {avatarProps && (\n <Avatar\n type=\"image\"\n {...avatarProps}\n size=\"small\"\n shape=\"circle\"\n className={classNames(\n 'ndl-ai-user-bubble-avatar',\n avatarProps?.className,\n )}\n />\n )}\n <div className=\"ndl-ai-user-bubble-main\">\n <Typography\n as=\"div\"\n variant=\"body-medium\"\n ref={contentRef}\n className={classNames('ndl-ai-user-bubble-content', {\n 'ndl-ai-user-bubble-content-clamped':\n isCollapseEnabled && !isExpanded,\n })}\n style={\n isCollapseEnabled\n ? ({\n '--ndl-ai-user-bubble-collapsed-lines': maxLines,\n } as React.CSSProperties)\n : undefined\n }\n >\n {children}\n {hasOverflow && isExpanded && (\n <span\n className=\"ndl-ai-user-bubble-expand-spacer\"\n aria-hidden=\"true\"\n />\n )}\n </Typography>\n {hasOverflow && (\n <div className=\"ndl-ai-user-bubble-toggle\">{expandButton}</div>\n )}\n </div>\n <div className=\"ndl-ai-user-bubble-trailing\">{trailingElement}</div>\n </div>\n );\n};\n\nexport { UserBubbleComponent as UserBubble };\n"]}
@@ -24,11 +24,7 @@ const jsx_runtime_1 = require("react/jsx-runtime");
24
24
  require("@neo4j-ndl/base/lib/neo4j-ds-styles.css");
25
25
  const ai_1 = require("@neo4j-ndl/react/ai");
26
26
  const Component = () => {
27
- return ((0, jsx_runtime_1.jsx)(ai_1.UserBubble, { avatarProps: {
28
- name: 'KM',
29
- source: 'https://media.istockphoto.com/id/1334716681/photo/a-smiling-man.jpg?s=612x612&w=0&k=20&c=U6rkSDpQMzkcJEqx2hAa63fNLIhqnZb31Xuc_QSi648=',
30
- type: 'image',
31
- }, children: "Can you analyse my data and tell me about...?" }));
27
+ return (0, jsx_runtime_1.jsx)(ai_1.UserBubble, { children: "Can you analyse my data and tell me about...?" });
32
28
  };
33
29
  exports.default = Component;
34
30
  //# sourceMappingURL=user-bubble.story.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"user-bubble.story.js","sourceRoot":"","sources":["../../../../../src/ai/user-bubble/stories/user-bubble.story.tsx"],"names":[],"mappings":";;;AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,mDAAiD;AAEjD,4CAAiD;AAEjD,MAAM,SAAS,GAAG,GAAG,EAAE;IACrB,OAAO,CACL,uBAAC,eAAU,IACT,WAAW,EAAE;YACX,IAAI,EAAE,IAAI;YACV,MAAM,EACJ,uIAAuI;YACzI,IAAI,EAAE,OAAO;SACd,8DAGU,CACd,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 { UserBubble } from '@neo4j-ndl/react/ai';\n\nconst Component = () => {\n return (\n <UserBubble\n avatarProps={{\n name: 'KM',\n source:\n 'https://media.istockphoto.com/id/1334716681/photo/a-smiling-man.jpg?s=612x612&w=0&k=20&c=U6rkSDpQMzkcJEqx2hAa63fNLIhqnZb31Xuc_QSi648=',\n type: 'image',\n }}\n >\n Can you analyse my data and tell me about...?\n </UserBubble>\n );\n};\n\nexport default Component;\n"]}
1
+ {"version":3,"file":"user-bubble.story.js","sourceRoot":"","sources":["../../../../../src/ai/user-bubble/stories/user-bubble.story.tsx"],"names":[],"mappings":";;;AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,mDAAiD;AAEjD,4CAAiD;AAEjD,MAAM,SAAS,GAAG,GAAG,EAAE;IACrB,OAAO,uBAAC,eAAU,gEAA2D,CAAC;AAChF,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 { UserBubble } from '@neo4j-ndl/react/ai';\n\nconst Component = () => {\n return <UserBubble>Can you analyse my data and tell me about...?</UserBubble>;\n};\n\nexport default Component;\n"]}
@@ -9,7 +9,7 @@ var __rest = (this && this.__rest) || function (s, e) {
9
9
  }
10
10
  return t;
11
11
  };
12
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
12
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
13
13
  /**
14
14
  *
15
15
  * Copyright (c) "Neo4j"
@@ -30,8 +30,11 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
30
30
  * You should have received a copy of the GNU General Public License
31
31
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
32
32
  */
33
- import { Avatar, Typography } from '@neo4j-ndl/react';
33
+ import { Avatar, CleanIconButton, Typography } from '@neo4j-ndl/react';
34
34
  import classNames from 'classnames';
35
+ import { useLayoutEffect, useRef, useState } from 'react';
36
+ import { ChevronDownIconOutline } from '../../icons/generated/heroIcons/ChevronDownIconOutline';
37
+ import { ChevronUpIconOutline } from '../../icons/generated/heroIcons/ChevronUpIconOutline';
35
38
  /**
36
39
  * The component is used to display the user's message in a chat.
37
40
  * It has an avatar to represent the user and a trailing element to display potential additional actions.
@@ -39,9 +42,43 @@ import classNames from 'classnames';
39
42
  * @alpha - Changes to this component may be breaking.
40
43
  */
41
44
  const UserBubbleComponent = (_a) => {
42
- var { avatarProps, trailingElement, children, className, style, htmlAttributes, ref } = _a, restProps = __rest(_a, ["avatarProps", "trailingElement", "children", "className", "style", "htmlAttributes", "ref"]);
45
+ var { avatarProps, trailingElement, children, maxLines = 4, className, style, htmlAttributes, ref } = _a, restProps = __rest(_a, ["avatarProps", "trailingElement", "children", "maxLines", "className", "style", "htmlAttributes", "ref"]);
43
46
  const classes = classNames('ndl-ai-user-bubble', className);
44
- return (_jsxs("div", Object.assign({ ref: ref, className: classes, style: style }, restProps, htmlAttributes, { children: [_jsx(Avatar, Object.assign({ type: "image" }, avatarProps, { size: "small", shape: "circle", className: classNames('ndl-ai-user-bubble-avatar', avatarProps === null || avatarProps === void 0 ? void 0 : avatarProps.className) })), _jsx(Typography, { variant: "body-medium", className: "ndl-ai-user-bubble-content", children: children }), _jsx("div", { className: "ndl-ai-user-bubble-trailing", children: trailingElement })] })));
47
+ const contentRef = useRef(null);
48
+ const [isExpanded, setIsExpanded] = useState(false);
49
+ const [hasOverflow, setHasOverflow] = useState(false);
50
+ const isCollapseEnabled = maxLines !== null;
51
+ useLayoutEffect(() => {
52
+ const element = contentRef.current;
53
+ if (element === null || maxLines === null) {
54
+ setHasOverflow(false);
55
+ return;
56
+ }
57
+ const checkOverflow = () => {
58
+ const lineHeight = Number.parseFloat(window.getComputedStyle(element).lineHeight);
59
+ if (!Number.isFinite(lineHeight)) {
60
+ return;
61
+ }
62
+ setHasOverflow(element.scrollHeight > lineHeight * maxLines + 1);
63
+ };
64
+ checkOverflow();
65
+ const resizeObserver = new ResizeObserver(checkOverflow);
66
+ resizeObserver.observe(element);
67
+ return () => {
68
+ resizeObserver.disconnect();
69
+ };
70
+ }, [children, isExpanded, maxLines]);
71
+ const expandButton = hasOverflow ? (_jsxs("div", { className: "ndl-ai-user-bubble-expand-wrap", children: [_jsx(CleanIconButton, { className: "ndl-ai-user-bubble-expand", size: "small", onClick: () => setIsExpanded((expanded) => !expanded), description: isExpanded ? 'Show less' : 'Show more', htmlAttributes: {
72
+ 'aria-expanded': isExpanded,
73
+ type: 'button',
74
+ }, children: isExpanded ? _jsx(ChevronUpIconOutline, {}) : _jsx(ChevronDownIconOutline, {}) }), _jsxs(_Fragment, { children: [_jsx("div", { className: "ndl-ai-user-bubble-expand-blur", "aria-hidden": "true" }), _jsx("div", { className: "ndl-ai-user-bubble-expand-fill", "aria-hidden": "true" })] })] })) : null;
75
+ return (_jsxs("div", Object.assign({ ref: ref, className: classes, style: style }, restProps, htmlAttributes, { children: [avatarProps && (_jsx(Avatar, Object.assign({ type: "image" }, avatarProps, { size: "small", shape: "circle", className: classNames('ndl-ai-user-bubble-avatar', avatarProps === null || avatarProps === void 0 ? void 0 : avatarProps.className) }))), _jsxs("div", { className: "ndl-ai-user-bubble-main", children: [_jsxs(Typography, { as: "div", variant: "body-medium", ref: contentRef, className: classNames('ndl-ai-user-bubble-content', {
76
+ 'ndl-ai-user-bubble-content-clamped': isCollapseEnabled && !isExpanded,
77
+ }), style: isCollapseEnabled
78
+ ? {
79
+ '--ndl-ai-user-bubble-collapsed-lines': maxLines,
80
+ }
81
+ : undefined, children: [children, hasOverflow && isExpanded && (_jsx("span", { className: "ndl-ai-user-bubble-expand-spacer", "aria-hidden": "true" }))] }), hasOverflow && (_jsx("div", { className: "ndl-ai-user-bubble-toggle", children: expandButton }))] }), _jsx("div", { className: "ndl-ai-user-bubble-trailing", children: trailingElement })] })));
45
82
  };
46
83
  export { UserBubbleComponent as UserBubble };
47
84
  //# sourceMappingURL=UserBubble.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"UserBubble.js","sourceRoot":"","sources":["../../../../src/ai/user-bubble/UserBubble.tsx"],"names":[],"mappings":";;;;;;;;;;;;AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,UAAU,MAAM,YAAY,CAAC;AAapC;;;;;GAKG;AACH,MAAM,mBAAmB,GAAG,CAAC,EASS,EAAE,EAAE;QATb,EAC3B,WAAW,EACX,eAAe,EACf,QAAQ,EACR,SAAS,EACT,KAAK,EACL,cAAc,EACd,GAAG,OAEiC,EADjC,SAAS,cARe,6FAS5B,CADa;IAEZ,MAAM,OAAO,GAAG,UAAU,CAAC,oBAAoB,EAAE,SAAS,CAAC,CAAC;IAE5D,OAAO,CACL,6BACE,GAAG,EAAE,GAAG,EACR,SAAS,EAAE,OAAO,EAClB,KAAK,EAAE,KAAK,IACR,SAAS,EACT,cAAc,eAElB,KAAC,MAAM,kBACL,IAAI,EAAC,OAAO,IACR,WAAW,IACf,IAAI,EAAC,OAAO,EACZ,KAAK,EAAC,QAAQ,EACd,SAAS,EAAE,UAAU,CACnB,2BAA2B,EAC3B,WAAW,aAAX,WAAW,uBAAX,WAAW,CAAE,SAAS,CACvB,IACD,EACF,KAAC,UAAU,IAAC,OAAO,EAAC,aAAa,EAAC,SAAS,EAAC,4BAA4B,YACrE,QAAQ,GACE,EACb,cAAK,SAAS,EAAC,6BAA6B,YAAE,eAAe,GAAO,KAChE,CACP,CAAC;AACJ,CAAC,CAAC;AAEF,OAAO,EAAE,mBAAmB,IAAI,UAAU,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 { Avatar, Typography } from '@neo4j-ndl/react';\nimport classNames from 'classnames';\n\nimport type { CommonProps } from '../../_common/types';\n\ntype UserBubbleProps = {\n /** The content of the user bubble */\n children?: React.ReactNode;\n /** The props for the avatar */\n avatarProps?: React.ComponentProps<typeof Avatar>;\n /** The element to display after the content. Could be a CleanIconButton to edit the user bubble. */\n trailingElement?: React.ReactNode;\n};\n\n/**\n * The component is used to display the user's message in a chat.\n * It has an avatar to represent the user and a trailing element to display potential additional actions.\n *\n * @alpha - Changes to this component may be breaking.\n */\nconst UserBubbleComponent = ({\n avatarProps,\n trailingElement,\n children,\n className,\n style,\n htmlAttributes,\n ref,\n ...restProps\n}: CommonProps<'div', UserBubbleProps>) => {\n const classes = classNames('ndl-ai-user-bubble', className);\n\n return (\n <div\n ref={ref}\n className={classes}\n style={style}\n {...restProps}\n {...htmlAttributes}\n >\n <Avatar\n type=\"image\"\n {...avatarProps}\n size=\"small\"\n shape=\"circle\"\n className={classNames(\n 'ndl-ai-user-bubble-avatar',\n avatarProps?.className,\n )}\n />\n <Typography variant=\"body-medium\" className=\"ndl-ai-user-bubble-content\">\n {children}\n </Typography>\n <div className=\"ndl-ai-user-bubble-trailing\">{trailingElement}</div>\n </div>\n );\n};\n\nexport { UserBubbleComponent as UserBubble };\n"]}
1
+ {"version":3,"file":"UserBubble.js","sourceRoot":"","sources":["../../../../src/ai/user-bubble/UserBubble.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 { Avatar, CleanIconButton, Typography } from '@neo4j-ndl/react';\nimport classNames from 'classnames';\nimport { useLayoutEffect, useRef, useState } from 'react';\n\nimport type { CommonProps } from '../../_common/types';\nimport { ChevronDownIconOutline } from '../../icons/generated/heroIcons/ChevronDownIconOutline';\nimport { ChevronUpIconOutline } from '../../icons/generated/heroIcons/ChevronUpIconOutline';\n\ntype UserBubbleProps = {\n /** The content of the user bubble */\n children?: React.ReactNode;\n /** The props for the avatar */\n avatarProps?: React.ComponentProps<typeof Avatar>;\n /** The element to display after the content. Could be a CleanIconButton to edit the user bubble. */\n trailingElement?: React.ReactNode;\n /**\n * Maximum number of lines visible before the message is collapsed.\n * Set to `null` to always show the full message.\n * @default 4\n */\n maxLines?: number | null;\n};\n\n/**\n * The component is used to display the user's message in a chat.\n * It has an avatar to represent the user and a trailing element to display potential additional actions.\n *\n * @alpha - Changes to this component may be breaking.\n */\nconst UserBubbleComponent = ({\n avatarProps,\n trailingElement,\n children,\n maxLines = 4,\n className,\n style,\n htmlAttributes,\n ref,\n ...restProps\n}: CommonProps<'div', UserBubbleProps>) => {\n const classes = classNames('ndl-ai-user-bubble', className);\n const contentRef = useRef<HTMLDivElement>(null);\n const [isExpanded, setIsExpanded] = useState(false);\n const [hasOverflow, setHasOverflow] = useState(false);\n const isCollapseEnabled = maxLines !== null;\n\n useLayoutEffect(() => {\n const element = contentRef.current;\n if (element === null || maxLines === null) {\n setHasOverflow(false);\n return;\n }\n\n const checkOverflow = () => {\n const lineHeight = Number.parseFloat(\n window.getComputedStyle(element).lineHeight,\n );\n if (!Number.isFinite(lineHeight)) {\n return;\n }\n\n setHasOverflow(element.scrollHeight > lineHeight * maxLines + 1);\n };\n\n checkOverflow();\n\n const resizeObserver = new ResizeObserver(checkOverflow);\n resizeObserver.observe(element);\n\n return () => {\n resizeObserver.disconnect();\n };\n }, [children, isExpanded, maxLines]);\n\n const expandButton = hasOverflow ? (\n <div className=\"ndl-ai-user-bubble-expand-wrap\">\n <CleanIconButton\n className=\"ndl-ai-user-bubble-expand\"\n size=\"small\"\n onClick={() => setIsExpanded((expanded) => !expanded)}\n description={isExpanded ? 'Show less' : 'Show more'}\n htmlAttributes={{\n 'aria-expanded': isExpanded,\n type: 'button',\n }}\n >\n {isExpanded ? <ChevronUpIconOutline /> : <ChevronDownIconOutline />}\n </CleanIconButton>\n <>\n <div className=\"ndl-ai-user-bubble-expand-blur\" aria-hidden=\"true\" />\n <div className=\"ndl-ai-user-bubble-expand-fill\" aria-hidden=\"true\" />\n </>\n </div>\n ) : null;\n\n return (\n <div\n ref={ref}\n className={classes}\n style={style}\n {...restProps}\n {...htmlAttributes}\n >\n {avatarProps && (\n <Avatar\n type=\"image\"\n {...avatarProps}\n size=\"small\"\n shape=\"circle\"\n className={classNames(\n 'ndl-ai-user-bubble-avatar',\n avatarProps?.className,\n )}\n />\n )}\n <div className=\"ndl-ai-user-bubble-main\">\n <Typography\n as=\"div\"\n variant=\"body-medium\"\n ref={contentRef}\n className={classNames('ndl-ai-user-bubble-content', {\n 'ndl-ai-user-bubble-content-clamped':\n isCollapseEnabled && !isExpanded,\n })}\n style={\n isCollapseEnabled\n ? ({\n '--ndl-ai-user-bubble-collapsed-lines': maxLines,\n } as React.CSSProperties)\n : undefined\n }\n >\n {children}\n {hasOverflow && isExpanded && (\n <span\n className=\"ndl-ai-user-bubble-expand-spacer\"\n aria-hidden=\"true\"\n />\n )}\n </Typography>\n {hasOverflow && (\n <div className=\"ndl-ai-user-bubble-toggle\">{expandButton}</div>\n )}\n </div>\n <div className=\"ndl-ai-user-bubble-trailing\">{trailingElement}</div>\n </div>\n );\n};\n\nexport { UserBubbleComponent as UserBubble };\n"]}
@@ -22,11 +22,7 @@ import { jsx as _jsx } from "react/jsx-runtime";
22
22
  import '@neo4j-ndl/base/lib/neo4j-ds-styles.css';
23
23
  import { UserBubble } from '@neo4j-ndl/react/ai';
24
24
  const Component = () => {
25
- return (_jsx(UserBubble, { avatarProps: {
26
- name: 'KM',
27
- source: 'https://media.istockphoto.com/id/1334716681/photo/a-smiling-man.jpg?s=612x612&w=0&k=20&c=U6rkSDpQMzkcJEqx2hAa63fNLIhqnZb31Xuc_QSi648=',
28
- type: 'image',
29
- }, children: "Can you analyse my data and tell me about...?" }));
25
+ return _jsx(UserBubble, { children: "Can you analyse my data and tell me about...?" });
30
26
  };
31
27
  export default Component;
32
28
  //# sourceMappingURL=user-bubble.story.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"user-bubble.story.js","sourceRoot":"","sources":["../../../../../src/ai/user-bubble/stories/user-bubble.story.tsx"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,yCAAyC,CAAC;AAEjD,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEjD,MAAM,SAAS,GAAG,GAAG,EAAE;IACrB,OAAO,CACL,KAAC,UAAU,IACT,WAAW,EAAE;YACX,IAAI,EAAE,IAAI;YACV,MAAM,EACJ,uIAAuI;YACzI,IAAI,EAAE,OAAO;SACd,8DAGU,CACd,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 { UserBubble } from '@neo4j-ndl/react/ai';\n\nconst Component = () => {\n return (\n <UserBubble\n avatarProps={{\n name: 'KM',\n source:\n 'https://media.istockphoto.com/id/1334716681/photo/a-smiling-man.jpg?s=612x612&w=0&k=20&c=U6rkSDpQMzkcJEqx2hAa63fNLIhqnZb31Xuc_QSi648=',\n type: 'image',\n }}\n >\n Can you analyse my data and tell me about...?\n </UserBubble>\n );\n};\n\nexport default Component;\n"]}
1
+ {"version":3,"file":"user-bubble.story.js","sourceRoot":"","sources":["../../../../../src/ai/user-bubble/stories/user-bubble.story.tsx"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,yCAAyC,CAAC;AAEjD,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEjD,MAAM,SAAS,GAAG,GAAG,EAAE;IACrB,OAAO,KAAC,UAAU,gEAA2D,CAAC;AAChF,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 { UserBubble } from '@neo4j-ndl/react/ai';\n\nconst Component = () => {\n return <UserBubble>Can you analyse my data and tell me about...?</UserBubble>;\n};\n\nexport default Component;\n"]}
@@ -27,6 +27,12 @@ type UserBubbleProps = {
27
27
  avatarProps?: React.ComponentProps<typeof Avatar>;
28
28
  /** The element to display after the content. Could be a CleanIconButton to edit the user bubble. */
29
29
  trailingElement?: React.ReactNode;
30
+ /**
31
+ * Maximum number of lines visible before the message is collapsed.
32
+ * Set to `null` to always show the full message.
33
+ * @default 4
34
+ */
35
+ maxLines?: number | null;
30
36
  };
31
37
  /**
32
38
  * The component is used to display the user's message in a chat.
@@ -34,6 +40,6 @@ type UserBubbleProps = {
34
40
  *
35
41
  * @alpha - Changes to this component may be breaking.
36
42
  */
37
- declare const UserBubbleComponent: ({ avatarProps, trailingElement, children, className, style, htmlAttributes, ref, ...restProps }: CommonProps<"div", UserBubbleProps>) => import("react/jsx-runtime").JSX.Element;
43
+ declare const UserBubbleComponent: ({ avatarProps, trailingElement, children, maxLines, className, style, htmlAttributes, ref, ...restProps }: CommonProps<"div", UserBubbleProps>) => import("react/jsx-runtime").JSX.Element;
38
44
  export { UserBubbleComponent as UserBubble };
39
45
  //# sourceMappingURL=UserBubble.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"UserBubble.d.ts","sourceRoot":"","sources":["../../../../src/ai/user-bubble/UserBubble.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAAE,MAAM,EAAc,MAAM,kBAAkB,CAAC;AAGtD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAEvD,KAAK,eAAe,GAAG;IACrB,qCAAqC;IACrC,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,+BAA+B;IAC/B,WAAW,CAAC,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,MAAM,CAAC,CAAC;IAClD,oGAAoG;IACpG,eAAe,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CACnC,CAAC;AAEF;;;;;GAKG;AACH,QAAA,MAAM,mBAAmB,GAAI,iGAS1B,WAAW,CAAC,KAAK,EAAE,eAAe,CAAC,4CA2BrC,CAAC;AAEF,OAAO,EAAE,mBAAmB,IAAI,UAAU,EAAE,CAAC"}
1
+ {"version":3,"file":"UserBubble.d.ts","sourceRoot":"","sources":["../../../../src/ai/user-bubble/UserBubble.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAAE,MAAM,EAA+B,MAAM,kBAAkB,CAAC;AAIvE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAIvD,KAAK,eAAe,GAAG;IACrB,qCAAqC;IACrC,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,+BAA+B;IAC/B,WAAW,CAAC,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,MAAM,CAAC,CAAC;IAClD,oGAAoG;IACpG,eAAe,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAClC;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B,CAAC;AAEF;;;;;GAKG;AACH,QAAA,MAAM,mBAAmB,GAAI,2GAU1B,WAAW,CAAC,KAAK,EAAE,eAAe,CAAC,4CA4GrC,CAAC;AAEF,OAAO,EAAE,mBAAmB,IAAI,UAAU,EAAE,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"user-bubble.story.d.ts","sourceRoot":"","sources":["../../../../../src/ai/user-bubble/stories/user-bubble.story.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,yCAAyC,CAAC;AAIjD,QAAA,MAAM,SAAS,+CAad,CAAC;AAEF,eAAe,SAAS,CAAC"}
1
+ {"version":3,"file":"user-bubble.story.d.ts","sourceRoot":"","sources":["../../../../../src/ai/user-bubble/stories/user-bubble.story.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,yCAAyC,CAAC;AAIjD,QAAA,MAAM,SAAS,+CAEd,CAAC;AAEF,eAAe,SAAS,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neo4j-ndl/react",
3
- "version": "4.18.7",
3
+ "version": "4.18.8",
4
4
  "sideEffects": false,
5
5
  "description": "React implementation of Neo4j Design System",
6
6
  "keywords": [
@@ -399,7 +399,7 @@
399
399
  "@tanstack/react-table": "8.21.3",
400
400
  "react": ">=19.0.0",
401
401
  "react-dom": ">=19.0.0",
402
- "@neo4j-ndl/base": "^4.17.4"
402
+ "@neo4j-ndl/base": "^4.17.5"
403
403
  },
404
404
  "dependencies": {
405
405
  "@dnd-kit/core": "6.3.1",
@@ -10,6 +10,7 @@ Import: `import { UserBubbleComponent } from '@neo4j-ndl/react/ai'`
10
10
  |------|------|----------|---------|-------------|
11
11
  | `avatarProps` | `PolymorphicCommonProps<ElementType<any, keyof IntrinsicElements>, AvatarProps>` | | | The props for the avatar |
12
12
  | `children` | `ReactNode` | | | The content of the user bubble |
13
+ | `maxLines` | `number \| null` | | `4` | Maximum number of lines visible before the message is collapsed. Set to `null` to always show the full message. |
13
14
  | `ref` | `Ref<HTMLDivElement>` | | | A ref to apply to the root element. |
14
15
  | `trailingElement` | `ReactNode` | | | The element to display after the content. Could be a CleanIconButton to edit the user bubble. |
15
16