@databiosphere/findable-ui 49.5.0 → 50.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,3 +1,3 @@
1
1
  {
2
- ".": "49.5.0"
2
+ ".": "50.0.0"
3
3
  }
package/CHANGELOG.md CHANGED
@@ -1,5 +1,30 @@
1
1
  # Changelog
2
2
 
3
+ ## [50.0.0](https://github.com/DataBiosphere/findable-ui/compare/v49.6.0...v50.0.0) (2026-03-20)
4
+
5
+
6
+ ### ⚠ BREAKING CHANGES
7
+
8
+ * update minor dependencies to resolve npm audit vulnerabilities ([#828](https://github.com/DataBiosphere/findable-ui/issues/828))
9
+
10
+ ### Bug Fixes
11
+
12
+ * update 'open to terra' button to be a href ([#825](https://github.com/DataBiosphere/findable-ui/issues/825)) ([#826](https://github.com/DataBiosphere/findable-ui/issues/826)) ([49f686a](https://github.com/DataBiosphere/findable-ui/commit/49f686ac3eae32c9dbe3dfb1762f5c7a62a1ed12))
13
+ * update nih account title to include researcher auth service (ras) ([#832](https://github.com/DataBiosphere/findable-ui/issues/832)) ([#833](https://github.com/DataBiosphere/findable-ui/issues/833)) ([bc424e6](https://github.com/DataBiosphere/findable-ui/commit/bc424e66e2babe513faf12302070bec67554d4be))
14
+
15
+
16
+ ### Chores
17
+
18
+ * update minor dependencies to resolve npm audit vulnerabilities ([#827](https://github.com/DataBiosphere/findable-ui/issues/827)) ([954fe91](https://github.com/DataBiosphere/findable-ui/commit/954fe91ff941bb0abfedcb5dd0e10d773d6b5cd4))
19
+ * update minor dependencies to resolve npm audit vulnerabilities ([#828](https://github.com/DataBiosphere/findable-ui/issues/828)) ([954fe91](https://github.com/DataBiosphere/findable-ui/commit/954fe91ff941bb0abfedcb5dd0e10d773d6b5cd4))
20
+
21
+ ## [49.6.0](https://github.com/DataBiosphere/findable-ui/compare/v49.5.0...v49.6.0) (2026-03-12)
22
+
23
+
24
+ ### Features
25
+
26
+ * drop extracted mentions and mappings from chat response display ([#822](https://github.com/DataBiosphere/findable-ui/issues/822)) ([#823](https://github.com/DataBiosphere/findable-ui/issues/823)) ([a8a33e8](https://github.com/DataBiosphere/findable-ui/commit/a8a33e86a44f5707b15da60e585b8e25010e6d94))
27
+
3
28
  ## [49.5.0](https://github.com/DataBiosphere/findable-ui/compare/v49.4.1...v49.5.0) (2026-03-12)
4
29
 
5
30
 
@@ -1,11 +1,9 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { ButtonPrimary } from "../../../../../common/Button/components/ButtonPrimary/buttonPrimary";
3
2
  import { FluidPaper } from "../../../../../common/Paper/paper.styles";
4
3
  import { ANCHOR_TARGET, REL_ATTRIBUTE, } from "../../../../../Links/common/entities";
5
4
  import { Section, SectionActions, SectionContent, } from "../../../../export.styles";
5
+ import { BUTTON_PROPS } from "../../../../../../styles/common/mui/button";
6
+ import { Button, Link } from "@mui/material";
6
7
  export const ExportToTerraReady = ({ ExportToTerraSuccess, exportURL, }) => {
7
- const onOpenTerra = () => {
8
- window.open(exportURL, ANCHOR_TARGET.BLANK, REL_ATTRIBUTE.NO_OPENER_NO_REFERRER);
9
- };
10
- return (_jsx(FluidPaper, { children: _jsxs(Section, { children: [_jsx(SectionContent, { children: _jsx(ExportToTerraSuccess, {}) }), _jsx(SectionActions, { children: _jsx(ButtonPrimary, { onClick: onOpenTerra, children: "Open Terra" }) })] }) }));
8
+ return (_jsx(FluidPaper, { children: _jsxs(Section, { children: [_jsx(SectionContent, { children: _jsx(ExportToTerraSuccess, {}) }), _jsx(SectionActions, { children: _jsx(Button, { color: BUTTON_PROPS.COLOR.PRIMARY, component: Link, href: exportURL, rel: REL_ATTRIBUTE.NO_OPENER_NO_REFERRER, target: ANCHOR_TARGET.BLANK, variant: BUTTON_PROPS.VARIANT.CONTAINED, children: "Open Terra" }) })] }) }));
11
9
  };
@@ -6,5 +6,5 @@ export const ConnectTerraToNIHAccount = ({ active, completed, step, }) => {
6
6
  const onGotoTutorial = () => {
7
7
  window.open("https://support.terra.bio/hc/en-us/articles/32634034451099-RAS-Integration-for-AnVIL-Data-Launching-3-25-26", ANCHOR_TARGET.BLANK, REL_ATTRIBUTE.NO_OPENER_NO_REFERRER);
8
8
  };
9
- return (_jsx(FormStep, { action: _jsx(ButtonPrimary, { onClick: onGotoTutorial, children: "Go to Tutorial" }), active: active, completed: completed, step: step, text: _jsx("p", { children: "Next, connect your Terra account to your NIH account by following the tutorial below." }), title: "Connect Terra to your NIH account" }));
9
+ return (_jsx(FormStep, { action: _jsx(ButtonPrimary, { onClick: onGotoTutorial, children: "Go to Tutorial" }), active: active, completed: completed, step: step, text: _jsx("p", { children: "Next, connect your Terra account to your NIH Researcher Auth Service (RAS) account by following the tutorial below." }), title: "Connect Terra to your NIH Researcher Auth Service (RAS) account" }));
10
10
  };
@@ -4,6 +4,6 @@ import { AssistantMessageProps } from "./types";
4
4
  * Renders an assistant message.
5
5
  * @param props - Component props.
6
6
  * @param props.message - Assistant message.
7
- * @returns The assistant message element.
7
+ * @returns The assistant message element, or null if there is no message.
8
8
  */
9
- export declare const AssistantMessage: ({ message, }: AssistantMessageProps) => JSX.Element;
9
+ export declare const AssistantMessage: ({ message, }: AssistantMessageProps) => JSX.Element | null;
@@ -1,15 +1,14 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { Stack, Typography } from "@mui/material";
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { Typography } from "@mui/material";
3
3
  import { TYPOGRAPHY_PROPS } from "../../../../../../../styles/common/mui/typography";
4
- import { getMappings, getMentions } from "./utils";
5
4
  /**
6
5
  * Renders an assistant message.
7
6
  * @param props - Component props.
8
7
  * @param props.message - Assistant message.
9
- * @returns The assistant message element.
8
+ * @returns The assistant message element, or null if there is no message.
10
9
  */
11
10
  export const AssistantMessage = ({ message, }) => {
12
- const mentions = getMentions(message);
13
- const mappings = getMappings(message);
14
- return (_jsxs(Stack, { gap: 2, useFlexGap: true, children: [message.response.message && (_jsx(Typography, { variant: TYPOGRAPHY_PROPS.VARIANT.BODY_400, children: message.response.message })), mentions && (_jsxs(Typography, { variant: TYPOGRAPHY_PROPS.VARIANT.BODY_SMALL_400, children: [_jsx(Typography, { color: TYPOGRAPHY_PROPS.COLOR.INK_LIGHT, variant: TYPOGRAPHY_PROPS.VARIANT.BODY_SMALL_500, children: "Extracted mentions:" }), " ", mentions] })), mappings && (_jsxs(Typography, { variant: TYPOGRAPHY_PROPS.VARIANT.BODY_SMALL_400, children: [_jsx(Typography, { color: TYPOGRAPHY_PROPS.COLOR.INK_LIGHT, variant: TYPOGRAPHY_PROPS.VARIANT.BODY_SMALL_500, children: "Extracted mappings:" }), " ", mappings] }))] }));
11
+ if (!message.response.message)
12
+ return null;
13
+ return (_jsx(Typography, { variant: TYPOGRAPHY_PROPS.VARIANT.BODY_400, children: message.response.message }));
15
14
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@databiosphere/findable-ui",
3
- "version": "49.5.0",
3
+ "version": "50.0.0",
4
4
  "description": "",
5
5
  "scripts": {
6
6
  "test": "node --experimental-vm-modules node_modules/jest/bin/jest.js",
@@ -25,7 +25,7 @@
25
25
  "@commitlint/cli": "^20.2.0",
26
26
  "@commitlint/config-conventional": "^20.2.0",
27
27
  "@emotion/jest": "^11.14.2",
28
- "@next/eslint-plugin-next": "^15.5.9",
28
+ "@next/eslint-plugin-next": "^15.5.13",
29
29
  "@storybook/nextjs-vite": "^10.1.10",
30
30
  "@testing-library/react": "^16.3.1",
31
31
  "@types/d3": "^7.4.3",
@@ -36,7 +36,7 @@
36
36
  "@types/react-window": "^1.8.5",
37
37
  "@typescript-eslint/eslint-plugin": "^8.50.0",
38
38
  "eslint": "^8.57.1",
39
- "eslint-config-next": "^15.5.9",
39
+ "eslint-config-next": "^15.5.13",
40
40
  "eslint-config-prettier": "^10.1.8",
41
41
  "eslint-plugin-eslint-comments": "^3.2.0",
42
42
  "eslint-plugin-jsdoc": "^61.5.0",
@@ -69,7 +69,7 @@
69
69
  "gray-matter": "^4.0.3",
70
70
  "isomorphic-dompurify": "^2.34.0",
71
71
  "ky": "^1.7.2",
72
- "next": "^15.5.9",
72
+ "next": "^15.5.13",
73
73
  "next-auth": "^4.24.13",
74
74
  "next-mdx-remote": "^5.0.0",
75
75
  "react": "^19.2.3",
@@ -1,5 +1,4 @@
1
1
  import { JSX, ElementType } from "react";
2
- import { ButtonPrimary } from "../../../../../common/Button/components/ButtonPrimary/buttonPrimary";
3
2
  import { FluidPaper } from "../../../../../common/Paper/paper.styles";
4
3
  import {
5
4
  ANCHOR_TARGET,
@@ -10,6 +9,8 @@ import {
10
9
  SectionActions,
11
10
  SectionContent,
12
11
  } from "../../../../export.styles";
12
+ import { BUTTON_PROPS } from "../../../../../../styles/common/mui/button";
13
+ import { Button, Link } from "@mui/material";
13
14
 
14
15
  export interface ExportToTerraReadyProps {
15
16
  ExportToTerraSuccess: ElementType;
@@ -20,13 +21,6 @@ export const ExportToTerraReady = ({
20
21
  ExportToTerraSuccess,
21
22
  exportURL,
22
23
  }: ExportToTerraReadyProps): JSX.Element => {
23
- const onOpenTerra = (): void => {
24
- window.open(
25
- exportURL,
26
- ANCHOR_TARGET.BLANK,
27
- REL_ATTRIBUTE.NO_OPENER_NO_REFERRER,
28
- );
29
- };
30
24
  return (
31
25
  <FluidPaper>
32
26
  <Section>
@@ -34,7 +28,16 @@ export const ExportToTerraReady = ({
34
28
  <ExportToTerraSuccess />
35
29
  </SectionContent>
36
30
  <SectionActions>
37
- <ButtonPrimary onClick={onOpenTerra}>Open Terra</ButtonPrimary>
31
+ <Button
32
+ color={BUTTON_PROPS.COLOR.PRIMARY}
33
+ component={Link}
34
+ href={exportURL}
35
+ rel={REL_ATTRIBUTE.NO_OPENER_NO_REFERRER}
36
+ target={ANCHOR_TARGET.BLANK}
37
+ variant={BUTTON_PROPS.VARIANT.CONTAINED}
38
+ >
39
+ Open Terra
40
+ </Button>
38
41
  </SectionActions>
39
42
  </Section>
40
43
  </FluidPaper>
@@ -34,11 +34,11 @@ export const ConnectTerraToNIHAccount = ({
34
34
  step={step}
35
35
  text={
36
36
  <p>
37
- Next, connect your Terra account to your NIH account by following the
38
- tutorial below.
37
+ Next, connect your Terra account to your NIH Researcher Auth Service
38
+ (RAS) account by following the tutorial below.
39
39
  </p>
40
40
  }
41
- title="Connect Terra to your NIH account"
41
+ title="Connect Terra to your NIH Researcher Auth Service (RAS) account"
42
42
  />
43
43
  );
44
44
  };
@@ -1,49 +1,21 @@
1
- import { Stack, Typography } from "@mui/material";
1
+ import { Typography } from "@mui/material";
2
2
  import { JSX } from "react";
3
3
  import { AssistantMessageProps } from "./types";
4
4
  import { TYPOGRAPHY_PROPS } from "../../../../../../../styles/common/mui/typography";
5
- import { getMappings, getMentions } from "./utils";
6
5
 
7
6
  /**
8
7
  * Renders an assistant message.
9
8
  * @param props - Component props.
10
9
  * @param props.message - Assistant message.
11
- * @returns The assistant message element.
10
+ * @returns The assistant message element, or null if there is no message.
12
11
  */
13
12
  export const AssistantMessage = ({
14
13
  message,
15
- }: AssistantMessageProps): JSX.Element => {
16
- const mentions = getMentions(message);
17
- const mappings = getMappings(message);
14
+ }: AssistantMessageProps): JSX.Element | null => {
15
+ if (!message.response.message) return null;
18
16
  return (
19
- <Stack gap={2} useFlexGap>
20
- {message.response.message && (
21
- <Typography variant={TYPOGRAPHY_PROPS.VARIANT.BODY_400}>
22
- {message.response.message}
23
- </Typography>
24
- )}
25
- {mentions && (
26
- <Typography variant={TYPOGRAPHY_PROPS.VARIANT.BODY_SMALL_400}>
27
- <Typography
28
- color={TYPOGRAPHY_PROPS.COLOR.INK_LIGHT}
29
- variant={TYPOGRAPHY_PROPS.VARIANT.BODY_SMALL_500}
30
- >
31
- Extracted mentions:
32
- </Typography>{" "}
33
- {mentions}
34
- </Typography>
35
- )}
36
- {mappings && (
37
- <Typography variant={TYPOGRAPHY_PROPS.VARIANT.BODY_SMALL_400}>
38
- <Typography
39
- color={TYPOGRAPHY_PROPS.COLOR.INK_LIGHT}
40
- variant={TYPOGRAPHY_PROPS.VARIANT.BODY_SMALL_500}
41
- >
42
- Extracted mappings:
43
- </Typography>{" "}
44
- {mappings}
45
- </Typography>
46
- )}
47
- </Stack>
17
+ <Typography variant={TYPOGRAPHY_PROPS.VARIANT.BODY_400}>
18
+ {message.response.message}
19
+ </Typography>
48
20
  );
49
21
  };
@@ -1,13 +0,0 @@
1
- import { AssistantMessage } from "../../../../../state/types";
2
- /**
3
- * Formats mention mappings from an assistant message as a readable string.
4
- * @param message - Assistant message containing response mentions.
5
- * @returns Formatted facet-value mappings separated by slashes, or empty string if no mentions.
6
- */
7
- export declare function getMappings(message: AssistantMessage): string;
8
- /**
9
- * Extracts original mention text from an assistant message.
10
- * @param message - Assistant message containing response mentions.
11
- * @returns Comma-separated original mention text, or empty string if no mentions.
12
- */
13
- export declare function getMentions(message: AssistantMessage): string;
@@ -1,25 +0,0 @@
1
- /**
2
- * Formats mention mappings from an assistant message as a readable string.
3
- * @param message - Assistant message containing response mentions.
4
- * @returns Formatted facet-value mappings separated by slashes, or empty string if no mentions.
5
- */
6
- export function getMappings(message) {
7
- const mappings = message.response.query.mentions.reduce((acc, m) => {
8
- const key = m.exclude ? `${m.facet} (exclude)` : m.facet;
9
- acc[key] = [...(acc[key] || []), ...m.values];
10
- return acc;
11
- }, {});
12
- return Object.entries(mappings)
13
- .map(([facet, values]) => `${facet}: ${values.join(", ")}`)
14
- .join(" / ");
15
- }
16
- /**
17
- * Extracts original mention text from an assistant message.
18
- * @param message - Assistant message containing response mentions.
19
- * @returns Comma-separated original mention text, or empty string if no mentions.
20
- */
21
- export function getMentions(message) {
22
- return message.response.query.mentions
23
- .map((mention) => mention.originalText)
24
- .join(", ");
25
- }
@@ -1,31 +0,0 @@
1
- import { AssistantMessage } from "../../../../../state/types";
2
-
3
- /**
4
- * Formats mention mappings from an assistant message as a readable string.
5
- * @param message - Assistant message containing response mentions.
6
- * @returns Formatted facet-value mappings separated by slashes, or empty string if no mentions.
7
- */
8
- export function getMappings(message: AssistantMessage): string {
9
- const mappings = message.response.query.mentions.reduce<
10
- Record<string, string[]>
11
- >((acc, m) => {
12
- const key = m.exclude ? `${m.facet} (exclude)` : m.facet;
13
- acc[key] = [...(acc[key] || []), ...m.values];
14
- return acc;
15
- }, {});
16
-
17
- return Object.entries(mappings)
18
- .map(([facet, values]) => `${facet}: ${values.join(", ")}`)
19
- .join(" / ");
20
- }
21
-
22
- /**
23
- * Extracts original mention text from an assistant message.
24
- * @param message - Assistant message containing response mentions.
25
- * @returns Comma-separated original mention text, or empty string if no mentions.
26
- */
27
- export function getMentions(message: AssistantMessage): string {
28
- return message.response.query.mentions
29
- .map((mention) => mention.originalText)
30
- .join(", ");
31
- }
@@ -1,149 +0,0 @@
1
- import {
2
- getMappings,
3
- getMentions,
4
- } from "../src/views/ResearchView/assistant/components/Messages/components/AssistantMessage/utils";
5
- import {
6
- AssistantMessage,
7
- MESSAGE_TYPE,
8
- } from "../src/views/ResearchView/state/types";
9
-
10
- /**
11
- * Creates a mock AssistantMessage with the given mentions.
12
- * @param mentions - Array of mention objects.
13
- * @returns A mock AssistantMessage.
14
- */
15
- function mockMessage(
16
- mentions: AssistantMessage["response"]["query"]["mentions"],
17
- ): AssistantMessage {
18
- return {
19
- createdAt: Date.now(),
20
- response: {
21
- intent: "auto",
22
- message: null,
23
- query: {
24
- mentions,
25
- message: null,
26
- },
27
- timing: {
28
- lookupMs: 0,
29
- pipelineMs: 0,
30
- totalMs: 0,
31
- },
32
- },
33
- type: MESSAGE_TYPE.ASSISTANT,
34
- };
35
- }
36
-
37
- describe("getMappings", () => {
38
- it("returns empty string for empty mentions", () => {
39
- expect(getMappings(mockMessage([]))).toBe("");
40
- });
41
-
42
- it("formats a single mention", () => {
43
- const message = mockMessage([
44
- {
45
- exclude: false,
46
- facet: "disease",
47
- originalText: "T2D",
48
- values: ["T2D"],
49
- },
50
- ]);
51
- expect(getMappings(message)).toBe("disease: T2D");
52
- });
53
-
54
- it("formats a mention with multiple values", () => {
55
- const message = mockMessage([
56
- {
57
- exclude: false,
58
- facet: "disease",
59
- originalText: "cancer",
60
- values: ["lung cancer", "breast cancer"],
61
- },
62
- ]);
63
- expect(getMappings(message)).toBe("disease: lung cancer, breast cancer");
64
- });
65
-
66
- it("groups mentions by facet", () => {
67
- const message = mockMessage([
68
- {
69
- exclude: false,
70
- facet: "disease",
71
- originalText: "T2D",
72
- values: ["T2D"],
73
- },
74
- {
75
- exclude: false,
76
- facet: "disease",
77
- originalText: "T1D",
78
- values: ["T1D"],
79
- },
80
- ]);
81
- expect(getMappings(message)).toBe("disease: T2D, T1D");
82
- });
83
-
84
- it("separates different facets with slashes", () => {
85
- const message = mockMessage([
86
- {
87
- exclude: false,
88
- facet: "disease",
89
- originalText: "T2D",
90
- values: ["T2D"],
91
- },
92
- {
93
- exclude: false,
94
- facet: "data_type",
95
- originalText: "WGS",
96
- values: ["WGS"],
97
- },
98
- ]);
99
- expect(getMappings(message)).toBe("disease: T2D / data_type: WGS");
100
- });
101
-
102
- it("marks excluded facets", () => {
103
- const message = mockMessage([
104
- {
105
- exclude: true,
106
- facet: "disease",
107
- originalText: "T2D",
108
- values: ["T2D"],
109
- },
110
- ]);
111
- expect(getMappings(message)).toBe("disease (exclude): T2D");
112
- });
113
- });
114
-
115
- describe("getMentions", () => {
116
- it("returns empty string for empty mentions", () => {
117
- expect(getMentions(mockMessage([]))).toBe("");
118
- });
119
-
120
- it("returns original text for a single mention", () => {
121
- const message = mockMessage([
122
- {
123
- exclude: false,
124
- facet: "disease",
125
- originalText: "T2D",
126
- values: ["T2D"],
127
- },
128
- ]);
129
- expect(getMentions(message)).toBe("T2D");
130
- });
131
-
132
- it("joins multiple mentions with commas", () => {
133
- const message = mockMessage([
134
- {
135
- exclude: false,
136
- facet: "disease",
137
- originalText: "T2D",
138
- values: ["T2D"],
139
- },
140
- {
141
- exclude: false,
142
- facet: "data_type",
143
- originalText: "WGS",
144
- values: ["WGS"],
145
- },
146
- ]);
147
- expect(getMentions(message)).toBe("T2D, WGS");
148
- });
149
- });