@databiosphere/findable-ui 39.0.0 → 40.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.
- package/.release-please-manifest.json +1 -1
- package/CHANGELOG.md +23 -0
- package/lib/components/DataDictionary/components/Entities/entities.d.ts +1 -1
- package/lib/components/DataDictionary/components/Entities/entities.js +2 -2
- package/lib/components/DataDictionary/components/Entities/types.d.ts +0 -2
- package/lib/components/DataDictionary/components/Entity/entity.d.ts +1 -1
- package/lib/components/DataDictionary/components/Entity/entity.js +3 -3
- package/lib/components/DataDictionary/components/Entity/entity.styles.js +0 -2
- package/lib/components/DataDictionary/components/Entity/types.d.ts +0 -2
- package/lib/components/DataDictionary/components/Table/table.js +6 -8
- package/lib/components/DataDictionary/components/Table/table.styles.d.ts +7 -0
- package/lib/components/DataDictionary/components/Table/table.styles.js +8 -0
- package/lib/components/DataDictionary/dataDictionary.js +6 -1
- package/lib/components/Detail/components/Table/components/TableRows/components/CollapsableRows/collapsableRows.js +1 -1
- package/lib/components/Detail/components/Table/components/TableRows/tableRows.js +1 -1
- package/lib/components/Index/index.styles.js +3 -1
- package/lib/components/MarkdownRenderer/markdownRenderer.styles.js +3 -0
- package/lib/components/Table/components/TableCell/components/MarkdownCell/markdownCell.d.ts +1 -1
- package/lib/components/Table/components/TableCell/components/RankedCell/rankedCell.d.ts +2 -2
- package/lib/components/Table/components/TableCell/components/RankedCell/rankedCell.js +12 -4
- package/lib/components/common/AnchorLink/anchorLink.d.ts +3 -1
- package/lib/components/common/AnchorLink/anchorLink.js +2 -2
- package/lib/components/common/AnchorLink/anchorLink.styles.js +2 -2
- package/lib/hooks/useHtmlStyle/constants.d.ts +2 -0
- package/lib/hooks/useHtmlStyle/constants.js +3 -0
- package/lib/hooks/useHtmlStyle/hook.d.ts +2 -0
- package/lib/hooks/useHtmlStyle/hook.js +18 -0
- package/lib/hooks/useHtmlStyle/types.d.ts +2 -0
- package/lib/hooks/useHtmlStyle/types.js +1 -0
- package/package.json +4 -4
- package/src/components/DataDictionary/components/Entities/entities.tsx +1 -2
- package/src/components/DataDictionary/components/Entities/types.ts +0 -2
- package/src/components/DataDictionary/components/Entity/entity.styles.ts +1 -4
- package/src/components/DataDictionary/components/Entity/entity.tsx +9 -9
- package/src/components/DataDictionary/components/Entity/types.ts +0 -2
- package/src/components/DataDictionary/components/Table/table.styles.ts +9 -0
- package/src/components/DataDictionary/components/Table/table.tsx +17 -20
- package/src/components/DataDictionary/dataDictionary.tsx +7 -1
- package/src/components/Detail/components/Table/components/TableRows/components/CollapsableRows/collapsableRows.tsx +5 -1
- package/src/components/Detail/components/Table/components/TableRows/tableRows.tsx +1 -0
- package/src/components/Index/index.styles.ts +3 -1
- package/src/components/MarkdownRenderer/markdownRenderer.styles.ts +3 -0
- package/src/components/Table/components/TableCell/components/MarkdownCell/markdownCell.tsx +1 -1
- package/src/components/Table/components/TableCell/components/RankedCell/rankedCell.tsx +21 -4
- package/src/components/common/AnchorLink/anchorLink.styles.ts +2 -2
- package/src/components/common/AnchorLink/anchorLink.tsx +4 -1
- package/src/hooks/useHtmlStyle/constants.ts +5 -0
- package/src/hooks/useHtmlStyle/hook.ts +23 -0
- package/src/hooks/useHtmlStyle/types.ts +3 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,28 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [40.0.0](https://github.com/DataBiosphere/findable-ui/compare/v39.1.0...v40.0.0) (2025-07-24)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### ⚠ BREAKING CHANGES
|
|
7
|
+
|
|
8
|
+
* upgrade next js to 14.2.30 or greater ([#568](https://github.com/DataBiosphere/findable-ui/issues/568)) (#579)
|
|
9
|
+
|
|
10
|
+
### Bug Fixes
|
|
11
|
+
|
|
12
|
+
* fix markdown rendering overflow ([#551](https://github.com/DataBiosphere/findable-ui/issues/551)) ([#580](https://github.com/DataBiosphere/findable-ui/issues/580)) ([42ce935](https://github.com/DataBiosphere/findable-ui/commit/42ce9355b10997e29648e9685622dfe04db4e625))
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
### Chores
|
|
16
|
+
|
|
17
|
+
* upgrade next js to 14.2.30 or greater ([#568](https://github.com/DataBiosphere/findable-ui/issues/568)) ([#579](https://github.com/DataBiosphere/findable-ui/issues/579)) ([ff88c9c](https://github.com/DataBiosphere/findable-ui/commit/ff88c9ca9479f7ae736e9794b428cc1454d81d6c))
|
|
18
|
+
|
|
19
|
+
## [39.1.0](https://github.com/DataBiosphere/findable-ui/compare/v39.0.0...v39.1.0) (2025-07-24)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
### Features
|
|
23
|
+
|
|
24
|
+
* add row ids to data dictionary table for anchor link scrolling ([#576](https://github.com/DataBiosphere/findable-ui/issues/576)) ([#577](https://github.com/DataBiosphere/findable-ui/issues/577)) ([bd7d05b](https://github.com/DataBiosphere/findable-ui/commit/bd7d05b451a7d9190b92fb682d892600cde17ba2))
|
|
25
|
+
|
|
3
26
|
## [39.0.0](https://github.com/DataBiosphere/findable-ui/compare/v38.3.0...v39.0.0) (2025-07-23)
|
|
4
27
|
|
|
5
28
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { RowData } from "@tanstack/react-table";
|
|
2
2
|
import { Attribute } from "../../../../common/entities";
|
|
3
3
|
import { ClassesProps } from "./types";
|
|
4
|
-
export declare const Entities: <T extends RowData = Attribute>({
|
|
4
|
+
export declare const Entities: <T extends RowData = Attribute>({ table, }: ClassesProps<T>) => JSX.Element;
|
|
@@ -3,10 +3,10 @@ import React from "react";
|
|
|
3
3
|
import { NoResults } from "../../../NoResults/noResults";
|
|
4
4
|
import { Entity } from "../Entity/entity";
|
|
5
5
|
import { GRID_PROPS, NO_RESULTS_PROPS } from "./constants";
|
|
6
|
-
export const Entities = ({
|
|
6
|
+
export const Entities = ({ table, }) => {
|
|
7
7
|
const { getGroupedRowModel } = table;
|
|
8
8
|
const { rows } = getGroupedRowModel();
|
|
9
9
|
if (rows.length === 0)
|
|
10
10
|
return React.createElement(NoResults, { ...NO_RESULTS_PROPS });
|
|
11
|
-
return (React.createElement(Grid, { ...GRID_PROPS }, rows.map((row) => (React.createElement(Entity, { key: row.id, row: row,
|
|
11
|
+
return (React.createElement(Grid, { ...GRID_PROPS }, rows.map((row) => (React.createElement(Entity, { key: row.id, row: row, table: table })))));
|
|
12
12
|
};
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import { RowData, Table } from "@tanstack/react-table";
|
|
2
2
|
import { Attribute } from "../../../../common/entities";
|
|
3
|
-
import { LayoutSpacing } from "../../../../hooks/UseLayoutSpacing/types";
|
|
4
3
|
export interface ClassesProps<T extends RowData = Attribute> {
|
|
5
|
-
spacing?: LayoutSpacing;
|
|
6
4
|
table: Table<T>;
|
|
7
5
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { RowData } from "@tanstack/react-table";
|
|
2
2
|
import { Attribute } from "../../../../common/entities";
|
|
3
3
|
import { EntityProps } from "./types";
|
|
4
|
-
export declare const Entity: <T extends RowData = Attribute>({ row,
|
|
4
|
+
export declare const Entity: <T extends RowData = Attribute>({ row, table, }: EntityProps<T>) => JSX.Element | null;
|
|
@@ -6,7 +6,7 @@ import { Table } from "../Table/table";
|
|
|
6
6
|
import { GRID_PROPS } from "./constants";
|
|
7
7
|
import { StyledTypography } from "./entity.styles";
|
|
8
8
|
import { getClassMeta } from "./utils";
|
|
9
|
-
export const Entity = ({ row,
|
|
9
|
+
export const Entity = ({ row, table, }) => {
|
|
10
10
|
// Get class key from row.
|
|
11
11
|
const classKey = row.getValue("classKey");
|
|
12
12
|
// Get class metadata from table options.
|
|
@@ -16,10 +16,10 @@ export const Entity = ({ row, spacing, table, }) => {
|
|
|
16
16
|
return null;
|
|
17
17
|
return (React.createElement(Grid, { ...GRID_PROPS, rowGap: 4 },
|
|
18
18
|
React.createElement(Grid, { ...GRID_PROPS, rowGap: 1 },
|
|
19
|
-
React.createElement(StyledTypography, { component: "h3", id: classKey, variant: TYPOGRAPHY_PROPS.VARIANT.TEXT_HEADING_SMALL
|
|
19
|
+
React.createElement(StyledTypography, { component: "h3", id: classKey, variant: TYPOGRAPHY_PROPS.VARIANT.TEXT_HEADING_SMALL },
|
|
20
20
|
cls.title,
|
|
21
21
|
" ",
|
|
22
22
|
React.createElement(AnchorLink, { anchorLink: classKey })),
|
|
23
|
-
React.createElement(Typography, { color: TYPOGRAPHY_PROPS.COLOR.INK_LIGHT, component: "div", variant: TYPOGRAPHY_PROPS.VARIANT.TEXT_BODY_400_2_LINES }, cls.description)),
|
|
23
|
+
cls.description && (React.createElement(Typography, { color: TYPOGRAPHY_PROPS.COLOR.INK_LIGHT, component: "div", variant: TYPOGRAPHY_PROPS.VARIANT.TEXT_BODY_400_2_LINES }, cls.description))),
|
|
24
24
|
React.createElement(Table, { row: row, table: table })));
|
|
25
25
|
};
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import { Row, RowData, Table } from "@tanstack/react-table";
|
|
2
2
|
import { Attribute } from "../../../../common/entities";
|
|
3
|
-
import { LayoutSpacing } from "../../../../hooks/UseLayoutSpacing/types";
|
|
4
3
|
export interface EntityProps<T extends RowData = Attribute> {
|
|
5
4
|
row: Row<T>;
|
|
6
|
-
spacing?: LayoutSpacing;
|
|
7
5
|
table: Table<T>;
|
|
8
6
|
}
|
|
@@ -5,13 +5,11 @@ import { ROW_DIRECTION } from "../../../Table/common/entities";
|
|
|
5
5
|
import { TableHead } from "../../../Table/components/TableHead/tableHead";
|
|
6
6
|
import { GridTable } from "../../../Table/table.styles";
|
|
7
7
|
import { getColumnTrackSizing } from "../../../TableCreator/options/columnTrackSizing/utils";
|
|
8
|
-
import {
|
|
9
|
-
import { GridPaper } from "../../../common/Paper/paper.styles";
|
|
8
|
+
import { StyledRoundedPaper } from "./table.styles";
|
|
10
9
|
export const Table = ({ row, table, }) => {
|
|
11
|
-
return (React.createElement(
|
|
12
|
-
React.createElement(
|
|
13
|
-
React.createElement(
|
|
14
|
-
React.createElement(
|
|
15
|
-
|
|
16
|
-
React.createElement(TableBody, { rowDirection: ROW_DIRECTION.DEFAULT, rows: row.getLeafRows(), tableInstance: table }))))));
|
|
10
|
+
return (React.createElement(StyledRoundedPaper, { elevation: 0 },
|
|
11
|
+
React.createElement(TableContainer, null,
|
|
12
|
+
React.createElement(GridTable, { gridTemplateColumns: getColumnTrackSizing(table.getVisibleFlatColumns()) },
|
|
13
|
+
React.createElement(TableHead, { tableInstance: table }),
|
|
14
|
+
React.createElement(TableBody, { rowDirection: ROW_DIRECTION.DEFAULT, rows: row.getLeafRows(), tableInstance: table })))));
|
|
17
15
|
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export declare const StyledRoundedPaper: import("@emotion/styled").StyledComponent<import("../../../types").BaseComponentProps & import("@mui/material").PaperOwnProps & import("@mui/material/OverridableComponent").CommonProps & Omit<Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & {
|
|
2
|
+
ref?: ((instance: HTMLDivElement | null) => void | import("react").DO_NOT_USE_OR_YOU_WILL_BE_FIRED_CALLBACK_REF_RETURN_VALUES[keyof import("react").DO_NOT_USE_OR_YOU_WILL_BE_FIRED_CALLBACK_REF_RETURN_VALUES]) | import("react").RefObject<HTMLDivElement> | null | undefined;
|
|
3
|
+
}, "style" | "className" | "classes" | "children" | "sx" | "elevation" | "square" | "variant"> & {
|
|
4
|
+
component?: React.ElementType;
|
|
5
|
+
} & {
|
|
6
|
+
theme?: import("@emotion/react").Theme;
|
|
7
|
+
}, {}, {}>;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import styled from "@emotion/styled";
|
|
2
|
+
import { PALETTE } from "../../../../styles/common/constants/palette";
|
|
3
|
+
import { RoundedPaper } from "../../../common/Paper/components/RoundedPaper/roundedPaper";
|
|
4
|
+
export const StyledRoundedPaper = styled(RoundedPaper) `
|
|
5
|
+
background-color: ${PALETTE.SMOKE_MAIN};
|
|
6
|
+
display: grid;
|
|
7
|
+
gap: 1px;
|
|
8
|
+
`;
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { Fade } from "@mui/material";
|
|
2
2
|
import React from "react";
|
|
3
|
+
import { PROPERTY } from "../../hooks/useHtmlStyle/constants";
|
|
4
|
+
import { useHtmlStyle } from "../../hooks/useHtmlStyle/hook";
|
|
3
5
|
import { useLayoutSpacing } from "../../hooks/UseLayoutSpacing/hook";
|
|
4
6
|
import { Description } from "./components/Description/description";
|
|
5
7
|
import { Entities } from "./components/Entities/entities";
|
|
@@ -30,6 +32,9 @@ export const DataDictionary = ({ className, dictionary, EntitiesLayout = Default
|
|
|
30
32
|
const table = useTable(dictionary, classes, tableOptions);
|
|
31
33
|
// Dictionary outline.
|
|
32
34
|
const outline = buildClassesOutline(table);
|
|
35
|
+
// Update scroll-padding-top on the HTML element.
|
|
36
|
+
// Scroll-snaps table rows to below the sticky filters.
|
|
37
|
+
useHtmlStyle(PROPERTY.SCROLL_PADDING_TOP, `${dimensions.height}px`);
|
|
33
38
|
return (React.createElement(Fade, { in: spacing.top > 0 },
|
|
34
39
|
React.createElement(View, { className: className },
|
|
35
40
|
React.createElement(TitleLayout, { ...spacing },
|
|
@@ -42,5 +47,5 @@ export const DataDictionary = ({ className, dictionary, EntitiesLayout = Default
|
|
|
42
47
|
React.createElement(Fade, { in: dimensions.height > 0 },
|
|
43
48
|
React.createElement(EntitiesLayout, { spacing: entitiesSpacing },
|
|
44
49
|
React.createElement(Description, { description: description }),
|
|
45
|
-
React.createElement(Entities, {
|
|
50
|
+
React.createElement(Entities, { table: table }))))));
|
|
46
51
|
};
|
|
@@ -10,7 +10,7 @@ export const CollapsableRows = ({ rows: leafOrSubRows, tableInstance, }) => {
|
|
|
10
10
|
return (React.createElement(Fragment, null, (leafOrSubRows || rows).map((row) => {
|
|
11
11
|
if (row.depth > 0)
|
|
12
12
|
return null; // Hide sub rows.
|
|
13
|
-
return (React.createElement(StyledTableRow, { key: row.id, isPreview: row.getIsPreview() },
|
|
13
|
+
return (React.createElement(StyledTableRow, { key: row.id, id: row.id, isPreview: row.getIsPreview() },
|
|
14
14
|
React.createElement(CollapsableCell, { isDisabled: isCollapsableRowDisabled(tableInstance), row: row })));
|
|
15
15
|
})));
|
|
16
16
|
};
|
|
@@ -10,7 +10,7 @@ export const TableRows = ({ rows: leafOrSubRows, tableInstance, tableView, }) =>
|
|
|
10
10
|
const { tableCell } = tableView || {};
|
|
11
11
|
const { size: tableCellSize = "medium" } = tableCell || {};
|
|
12
12
|
return (React.createElement(Fragment, null, (leafOrSubRows || rows).map((row) => {
|
|
13
|
-
return (React.createElement(StyledTableRow, { key: row.id, canExpand: row.getCanExpand(), isExpanded: row.getIsExpanded(), isGrouped: row.getIsGrouped(), isPreview: row.getIsPreview(), onClick: () => handleToggleExpanded(row) }, row.getVisibleCells().map((cell) => {
|
|
13
|
+
return (React.createElement(StyledTableRow, { key: row.id, id: row.id, canExpand: row.getCanExpand(), isExpanded: row.getIsExpanded(), isGrouped: row.getIsGrouped(), isPreview: row.getIsPreview(), onClick: () => handleToggleExpanded(row) }, row.getVisibleCells().map((cell) => {
|
|
14
14
|
if (cell.getIsAggregated())
|
|
15
15
|
return null; // Display of aggregated cells is currently not supported.
|
|
16
16
|
if (cell.getIsPlaceholder())
|
|
@@ -3,7 +3,9 @@ import { Grid } from "@mui/material";
|
|
|
3
3
|
import { PALETTE } from "../../styles/common/constants/palette";
|
|
4
4
|
import { mediaTabletDown } from "../../styles/common/mixins/breakpoints";
|
|
5
5
|
import { FluidPaper } from "../common/Paper/components/FluidPaper/fluidPaper";
|
|
6
|
-
export const StyledGridEntityView = styled(Grid
|
|
6
|
+
export const StyledGridEntityView = styled(Grid, {
|
|
7
|
+
shouldForwardProp: (prop) => prop !== "bottom" && prop !== "top",
|
|
8
|
+
}) `
|
|
7
9
|
align-content: flex-start;
|
|
8
10
|
display: grid;
|
|
9
11
|
flex: 1;
|
|
@@ -3,6 +3,9 @@ import styled from "@emotion/styled";
|
|
|
3
3
|
// See https://github.com/emotion-js/emotion/releases/tag/%40emotion%2Fcache%4011.10.2.
|
|
4
4
|
const ignoreSsrWarning = "/* emotion-disable-server-rendering-unsafe-selector-warning-please-do-not-use-this-the-warning-exists-for-a-reason */";
|
|
5
5
|
export const StyledContainer = styled("div") `
|
|
6
|
+
min-width: 0;
|
|
7
|
+
width: 100%;
|
|
8
|
+
|
|
6
9
|
> *:first-child:not(style)${ignoreSsrWarning} {
|
|
7
10
|
margin-top: 0;
|
|
8
11
|
}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { CellContext, RowData } from "@tanstack/react-table";
|
|
2
|
-
import { BaseComponentProps } from "
|
|
2
|
+
import { BaseComponentProps } from "../../../../../types";
|
|
3
3
|
export declare const MarkdownCell: <T extends RowData, TValue extends string = string>({ className, column, getValue, row, table, }: BaseComponentProps & CellContext<T, TValue>) => JSX.Element | null;
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { CellContext, RowData } from "@tanstack/react-table";
|
|
2
|
-
import { BaseComponentProps } from "../../../../../types";
|
|
3
|
-
export declare const RankedCell: <T extends RowData, TValue = string | undefined | null>({ className, column, getValue, row, table, }: BaseComponentProps & CellContext<T, TValue>) => JSX.Element | null;
|
|
2
|
+
import { BaseComponentProps, ChildrenProps } from "../../../../../types";
|
|
3
|
+
export declare const RankedCell: <T extends RowData, TValue = string | undefined | null>({ children, className, column, getValue, row, table, }: BaseComponentProps & CellContext<T, TValue> & ChildrenProps) => JSX.Element | null;
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import React, { Fragment } from "react";
|
|
2
2
|
import { getTokens, getTokensRegex, isRankedCell } from "./utils";
|
|
3
|
-
export const RankedCell = ({
|
|
3
|
+
export const RankedCell = ({
|
|
4
|
+
/* children - e.g. AnchorLink component */
|
|
5
|
+
children, className, column, getValue, row, table, }) => {
|
|
4
6
|
// Get the cell value.
|
|
5
7
|
const value = getValue();
|
|
6
8
|
// If the cell value is undefined or null, return null.
|
|
@@ -12,14 +14,20 @@ export const RankedCell = ({ className, column, getValue, row, table, }) => {
|
|
|
12
14
|
const isRanked = isRankedCell(table, row, column.id);
|
|
13
15
|
// Return the unranked cell, as-is.
|
|
14
16
|
if (!isRanked)
|
|
15
|
-
return React.createElement(Fragment, null,
|
|
17
|
+
return (React.createElement(Fragment, null,
|
|
18
|
+
stringValue,
|
|
19
|
+
children));
|
|
16
20
|
// Tokenise the current global filter.
|
|
17
21
|
const tokens = getTokens(table);
|
|
18
22
|
// If there are no tokens, return the value as-is.
|
|
19
23
|
if (tokens.length === 0)
|
|
20
|
-
return React.createElement(Fragment, null,
|
|
24
|
+
return (React.createElement(Fragment, null,
|
|
25
|
+
stringValue,
|
|
26
|
+
children));
|
|
21
27
|
// Create regex pattern.
|
|
22
28
|
const regex = getTokensRegex(tokens);
|
|
23
29
|
// Return the ranked cell, with highlighting.
|
|
24
|
-
return (React.createElement("span", { className: className },
|
|
30
|
+
return (React.createElement("span", { className: className },
|
|
31
|
+
stringValue.split(regex).map((part, i) => (React.createElement(Fragment, { key: i }, part.match(regex) ? React.createElement("mark", null, part) : part))),
|
|
32
|
+
children));
|
|
25
33
|
};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { MouseEvent } from "react";
|
|
1
2
|
/**
|
|
2
3
|
* An anchor link component that provides deep linking functionality.
|
|
3
4
|
* @important The parent element must have `position: relative` CSS property
|
|
@@ -7,6 +8,7 @@
|
|
|
7
8
|
interface AnchorLinkProps {
|
|
8
9
|
anchorLink: string;
|
|
9
10
|
className?: string;
|
|
11
|
+
onClick?: (e: MouseEvent) => void;
|
|
10
12
|
}
|
|
11
|
-
export declare const AnchorLink: ({ anchorLink, className, }: AnchorLinkProps) => JSX.Element;
|
|
13
|
+
export declare const AnchorLink: ({ anchorLink, className, onClick, }: AnchorLinkProps) => JSX.Element;
|
|
12
14
|
export {};
|
|
@@ -2,8 +2,8 @@ import { LinkRounded } from "@mui/icons-material";
|
|
|
2
2
|
import { useRouter } from "next/router";
|
|
3
3
|
import React from "react";
|
|
4
4
|
import { StyledNextLink } from "./anchorLink.styles";
|
|
5
|
-
export const AnchorLink = ({ anchorLink, className, }) => {
|
|
5
|
+
export const AnchorLink = ({ anchorLink, className, onClick, }) => {
|
|
6
6
|
const { query } = useRouter();
|
|
7
|
-
return (React.createElement(StyledNextLink, { "aria-label": anchorLink, className: className, href: { hash: anchorLink, query } },
|
|
7
|
+
return (React.createElement(StyledNextLink, { "aria-label": anchorLink, className: className, href: { hash: anchorLink, query }, onClick: onClick },
|
|
8
8
|
React.createElement(LinkRounded, { fontSize: "xsmall" })));
|
|
9
9
|
};
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import styled from "@emotion/styled";
|
|
2
2
|
import Link from "next/link";
|
|
3
|
-
import {
|
|
3
|
+
import { PALETTE } from "../../../styles/common/constants/palette";
|
|
4
4
|
export const StyledNextLink = styled(Link) `
|
|
5
|
-
color: ${
|
|
5
|
+
color: ${PALETTE.INK_LIGHT};
|
|
6
6
|
margin-left: 4px;
|
|
7
7
|
opacity: 0;
|
|
8
8
|
position: absolute;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { useLayoutEffect } from "react";
|
|
2
|
+
export const useHtmlStyle = (property, value) => {
|
|
3
|
+
useLayoutEffect(() => {
|
|
4
|
+
// Get the HTML element.
|
|
5
|
+
const el = document.documentElement;
|
|
6
|
+
// Get the previous value.
|
|
7
|
+
const previousValue = el.style.getPropertyValue(property);
|
|
8
|
+
if (value !== null)
|
|
9
|
+
el.style.setProperty(property, value);
|
|
10
|
+
return () => {
|
|
11
|
+
// Restore or remove property value on the HTML element.
|
|
12
|
+
if (previousValue)
|
|
13
|
+
el.style.setProperty(property, previousValue);
|
|
14
|
+
else
|
|
15
|
+
el.style.removeProperty(property);
|
|
16
|
+
};
|
|
17
|
+
}, [property, value]);
|
|
18
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@databiosphere/findable-ui",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "40.0.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"test": "node --experimental-vm-modules node_modules/jest/bin/jest.js",
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"@commitlint/config-conventional": "^17.4.2",
|
|
27
27
|
"@emotion/jest": "^11.13.0",
|
|
28
28
|
"@mui/types": "^7.4.0",
|
|
29
|
-
"@next/eslint-plugin-next": "^14.2.
|
|
29
|
+
"@next/eslint-plugin-next": "^14.2.30",
|
|
30
30
|
"@storybook/addon-actions": "^8.6.4",
|
|
31
31
|
"@storybook/addon-essentials": "^8.6.4",
|
|
32
32
|
"@storybook/addon-interactions": "^8.6.4",
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
"@types/uuid": "8.3.4",
|
|
47
47
|
"@typescript-eslint/eslint-plugin": "^7.18.0",
|
|
48
48
|
"eslint": "^8.33.0",
|
|
49
|
-
"eslint-config-next": "^14.2.
|
|
49
|
+
"eslint-config-next": "^14.2.30",
|
|
50
50
|
"eslint-config-prettier": "^8.6.0",
|
|
51
51
|
"eslint-plugin-eslint-comments": "^3.2.0",
|
|
52
52
|
"eslint-plugin-jsdoc": "^48.1.0",
|
|
@@ -78,7 +78,7 @@
|
|
|
78
78
|
"copy-to-clipboard": "3.3.1",
|
|
79
79
|
"isomorphic-dompurify": "^2.22.0",
|
|
80
80
|
"ky": "^1.7.2",
|
|
81
|
-
"next": "^14.2.
|
|
81
|
+
"next": "^14.2.30",
|
|
82
82
|
"next-auth": "^4.24.7",
|
|
83
83
|
"react": "^18.3.1",
|
|
84
84
|
"react-dom": "^18.3.1",
|
|
@@ -8,7 +8,6 @@ import { GRID_PROPS, NO_RESULTS_PROPS } from "./constants";
|
|
|
8
8
|
import { ClassesProps } from "./types";
|
|
9
9
|
|
|
10
10
|
export const Entities = <T extends RowData = Attribute>({
|
|
11
|
-
spacing,
|
|
12
11
|
table,
|
|
13
12
|
}: ClassesProps<T>): JSX.Element => {
|
|
14
13
|
const { getGroupedRowModel } = table;
|
|
@@ -20,7 +19,7 @@ export const Entities = <T extends RowData = Attribute>({
|
|
|
20
19
|
<Grid {...GRID_PROPS}>
|
|
21
20
|
{/* Render grouped rows where each "group" is a class e.g. "donor" */}
|
|
22
21
|
{rows.map((row) => (
|
|
23
|
-
<Entity key={row.id} row={row}
|
|
22
|
+
<Entity key={row.id} row={row} table={table} />
|
|
24
23
|
))}
|
|
25
24
|
</Grid>
|
|
26
25
|
);
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import { RowData, Table } from "@tanstack/react-table";
|
|
2
2
|
import { Attribute } from "../../../../common/entities";
|
|
3
|
-
import { LayoutSpacing } from "../../../../hooks/UseLayoutSpacing/types";
|
|
4
3
|
|
|
5
4
|
export interface ClassesProps<T extends RowData = Attribute> {
|
|
6
|
-
spacing?: LayoutSpacing;
|
|
7
5
|
table: Table<T>;
|
|
8
6
|
}
|
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
import styled from "@emotion/styled";
|
|
2
2
|
import { Typography } from "@mui/material";
|
|
3
|
-
import { LayoutSpacing } from "../../../../hooks/UseLayoutSpacing/types";
|
|
4
|
-
|
|
5
|
-
export const StyledTypography = styled(Typography)<Partial<LayoutSpacing>>`
|
|
6
|
-
scroll-margin-top: ${({ top = 0 }) => top}px;
|
|
7
3
|
|
|
4
|
+
export const StyledTypography = styled(Typography)`
|
|
8
5
|
&:hover a {
|
|
9
6
|
opacity: 1;
|
|
10
7
|
}
|
|
@@ -12,7 +12,6 @@ import { getClassMeta } from "./utils";
|
|
|
12
12
|
|
|
13
13
|
export const Entity = <T extends RowData = Attribute>({
|
|
14
14
|
row,
|
|
15
|
-
spacing,
|
|
16
15
|
table,
|
|
17
16
|
}: EntityProps<T>): JSX.Element | null => {
|
|
18
17
|
// Get class key from row.
|
|
@@ -32,17 +31,18 @@ export const Entity = <T extends RowData = Attribute>({
|
|
|
32
31
|
component="h3"
|
|
33
32
|
id={classKey}
|
|
34
33
|
variant={TYPOGRAPHY_PROPS.VARIANT.TEXT_HEADING_SMALL}
|
|
35
|
-
{...spacing}
|
|
36
34
|
>
|
|
37
35
|
{cls.title} <AnchorLink anchorLink={classKey} />
|
|
38
36
|
</StyledTypography>
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
37
|
+
{cls.description && (
|
|
38
|
+
<Typography
|
|
39
|
+
color={TYPOGRAPHY_PROPS.COLOR.INK_LIGHT}
|
|
40
|
+
component="div"
|
|
41
|
+
variant={TYPOGRAPHY_PROPS.VARIANT.TEXT_BODY_400_2_LINES}
|
|
42
|
+
>
|
|
43
|
+
{cls.description}
|
|
44
|
+
</Typography>
|
|
45
|
+
)}
|
|
46
46
|
</Grid>
|
|
47
47
|
{/* Class attributes table */}
|
|
48
48
|
<Table row={row} table={table} />
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import { Row, RowData, Table } from "@tanstack/react-table";
|
|
2
2
|
import { Attribute } from "../../../../common/entities";
|
|
3
|
-
import { LayoutSpacing } from "../../../../hooks/UseLayoutSpacing/types";
|
|
4
3
|
|
|
5
4
|
export interface EntityProps<T extends RowData = Attribute> {
|
|
6
5
|
row: Row<T>;
|
|
7
|
-
spacing?: LayoutSpacing;
|
|
8
6
|
table: Table<T>;
|
|
9
7
|
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import styled from "@emotion/styled";
|
|
2
|
+
import { PALETTE } from "../../../../styles/common/constants/palette";
|
|
3
|
+
import { RoundedPaper } from "../../../common/Paper/components/RoundedPaper/roundedPaper";
|
|
4
|
+
|
|
5
|
+
export const StyledRoundedPaper = styled(RoundedPaper)`
|
|
6
|
+
background-color: ${PALETTE.SMOKE_MAIN};
|
|
7
|
+
display: grid;
|
|
8
|
+
gap: 1px;
|
|
9
|
+
`;
|
|
@@ -6,8 +6,7 @@ import { ROW_DIRECTION } from "../../../Table/common/entities";
|
|
|
6
6
|
import { TableHead } from "../../../Table/components/TableHead/tableHead";
|
|
7
7
|
import { GridTable } from "../../../Table/table.styles";
|
|
8
8
|
import { getColumnTrackSizing } from "../../../TableCreator/options/columnTrackSizing/utils";
|
|
9
|
-
import {
|
|
10
|
-
import { GridPaper } from "../../../common/Paper/paper.styles";
|
|
9
|
+
import { StyledRoundedPaper } from "./table.styles";
|
|
11
10
|
import { TableProps } from "./types";
|
|
12
11
|
|
|
13
12
|
export const Table = <T extends RowData>({
|
|
@@ -15,23 +14,21 @@ export const Table = <T extends RowData>({
|
|
|
15
14
|
table,
|
|
16
15
|
}: TableProps<T>): JSX.Element => {
|
|
17
16
|
return (
|
|
18
|
-
<
|
|
19
|
-
<
|
|
20
|
-
<
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
</GridPaper>
|
|
35
|
-
</RoundedPaper>
|
|
17
|
+
<StyledRoundedPaper elevation={0}>
|
|
18
|
+
<TableContainer>
|
|
19
|
+
<GridTable
|
|
20
|
+
gridTemplateColumns={getColumnTrackSizing(
|
|
21
|
+
table.getVisibleFlatColumns()
|
|
22
|
+
)}
|
|
23
|
+
>
|
|
24
|
+
<TableHead tableInstance={table} />
|
|
25
|
+
<TableBody
|
|
26
|
+
rowDirection={ROW_DIRECTION.DEFAULT}
|
|
27
|
+
rows={row.getLeafRows()}
|
|
28
|
+
tableInstance={table}
|
|
29
|
+
/>
|
|
30
|
+
</GridTable>
|
|
31
|
+
</TableContainer>
|
|
32
|
+
</StyledRoundedPaper>
|
|
36
33
|
);
|
|
37
34
|
};
|
|
@@ -2,6 +2,8 @@ import { Fade } from "@mui/material";
|
|
|
2
2
|
import { RowData } from "@tanstack/react-table";
|
|
3
3
|
import React from "react";
|
|
4
4
|
import { Attribute } from "../../common/entities";
|
|
5
|
+
import { PROPERTY } from "../../hooks/useHtmlStyle/constants";
|
|
6
|
+
import { useHtmlStyle } from "../../hooks/useHtmlStyle/hook";
|
|
5
7
|
import { useLayoutSpacing } from "../../hooks/UseLayoutSpacing/hook";
|
|
6
8
|
import { Description } from "./components/Description/description";
|
|
7
9
|
import { Entities } from "./components/Entities/entities";
|
|
@@ -48,6 +50,10 @@ export const DataDictionary = <T extends RowData = Attribute>({
|
|
|
48
50
|
// Dictionary outline.
|
|
49
51
|
const outline = buildClassesOutline<T>(table);
|
|
50
52
|
|
|
53
|
+
// Update scroll-padding-top on the HTML element.
|
|
54
|
+
// Scroll-snaps table rows to below the sticky filters.
|
|
55
|
+
useHtmlStyle(PROPERTY.SCROLL_PADDING_TOP, `${dimensions.height}px`);
|
|
56
|
+
|
|
51
57
|
return (
|
|
52
58
|
<Fade in={spacing.top > 0}>
|
|
53
59
|
{/* Fade in when header is measured. */}
|
|
@@ -66,7 +72,7 @@ export const DataDictionary = <T extends RowData = Attribute>({
|
|
|
66
72
|
{/* Fade in entities when filters are measured. */}
|
|
67
73
|
<EntitiesLayout spacing={entitiesSpacing}>
|
|
68
74
|
<Description description={description} />
|
|
69
|
-
<Entities
|
|
75
|
+
<Entities table={table} />
|
|
70
76
|
</EntitiesLayout>
|
|
71
77
|
</Fade>
|
|
72
78
|
</View>
|
|
@@ -27,7 +27,11 @@ export const CollapsableRows = <T extends RowData>({
|
|
|
27
27
|
{(leafOrSubRows || rows).map((row) => {
|
|
28
28
|
if (row.depth > 0) return null; // Hide sub rows.
|
|
29
29
|
return (
|
|
30
|
-
<StyledTableRow
|
|
30
|
+
<StyledTableRow
|
|
31
|
+
key={row.id}
|
|
32
|
+
id={row.id}
|
|
33
|
+
isPreview={row.getIsPreview()}
|
|
34
|
+
>
|
|
31
35
|
<CollapsableCell
|
|
32
36
|
isDisabled={isCollapsableRowDisabled(tableInstance)}
|
|
33
37
|
row={row}
|
|
@@ -5,7 +5,9 @@ import { PALETTE } from "../../styles/common/constants/palette";
|
|
|
5
5
|
import { mediaTabletDown } from "../../styles/common/mixins/breakpoints";
|
|
6
6
|
import { FluidPaper } from "../common/Paper/components/FluidPaper/fluidPaper";
|
|
7
7
|
|
|
8
|
-
export const StyledGridEntityView = styled(Grid
|
|
8
|
+
export const StyledGridEntityView = styled(Grid, {
|
|
9
|
+
shouldForwardProp: (prop) => prop !== "bottom" && prop !== "top",
|
|
10
|
+
})<LayoutSpacing>`
|
|
9
11
|
align-content: flex-start;
|
|
10
12
|
display: grid;
|
|
11
13
|
flex: 1;
|
|
@@ -6,6 +6,9 @@ const ignoreSsrWarning =
|
|
|
6
6
|
"/* emotion-disable-server-rendering-unsafe-selector-warning-please-do-not-use-this-the-warning-exists-for-a-reason */";
|
|
7
7
|
|
|
8
8
|
export const StyledContainer = styled("div")`
|
|
9
|
+
min-width: 0;
|
|
10
|
+
width: 100%;
|
|
11
|
+
|
|
9
12
|
> *:first-child:not(style)${ignoreSsrWarning} {
|
|
10
13
|
margin-top: 0;
|
|
11
14
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { CellContext, RowData } from "@tanstack/react-table";
|
|
2
|
-
import { BaseComponentProps } from "components/types";
|
|
3
2
|
import React from "react";
|
|
4
3
|
import { COMPONENTS } from "../../../../../MarkdownRenderer/constants";
|
|
4
|
+
import { BaseComponentProps } from "../../../../../types";
|
|
5
5
|
import { getTokens, getTokensRegex, isRankedCell } from "../RankedCell/utils";
|
|
6
6
|
import { StyledMarkdownRenderer } from "./markdownCell.styles";
|
|
7
7
|
|
|
@@ -1,18 +1,22 @@
|
|
|
1
1
|
import { CellContext, RowData } from "@tanstack/react-table";
|
|
2
2
|
import React, { Fragment } from "react";
|
|
3
|
-
import { BaseComponentProps } from "../../../../../types";
|
|
3
|
+
import { BaseComponentProps, ChildrenProps } from "../../../../../types";
|
|
4
4
|
import { getTokens, getTokensRegex, isRankedCell } from "./utils";
|
|
5
5
|
|
|
6
6
|
export const RankedCell = <
|
|
7
7
|
T extends RowData,
|
|
8
8
|
TValue = string | undefined | null
|
|
9
9
|
>({
|
|
10
|
+
/* children - e.g. AnchorLink component */
|
|
11
|
+
children,
|
|
10
12
|
className,
|
|
11
13
|
column,
|
|
12
14
|
getValue,
|
|
13
15
|
row,
|
|
14
16
|
table,
|
|
15
|
-
}: BaseComponentProps &
|
|
17
|
+
}: BaseComponentProps &
|
|
18
|
+
CellContext<T, TValue> &
|
|
19
|
+
ChildrenProps): JSX.Element | null => {
|
|
16
20
|
// Get the cell value.
|
|
17
21
|
const value = getValue();
|
|
18
22
|
|
|
@@ -26,13 +30,25 @@ export const RankedCell = <
|
|
|
26
30
|
const isRanked = isRankedCell(table, row, column.id);
|
|
27
31
|
|
|
28
32
|
// Return the unranked cell, as-is.
|
|
29
|
-
if (!isRanked)
|
|
33
|
+
if (!isRanked)
|
|
34
|
+
return (
|
|
35
|
+
<Fragment>
|
|
36
|
+
{stringValue}
|
|
37
|
+
{children}
|
|
38
|
+
</Fragment>
|
|
39
|
+
);
|
|
30
40
|
|
|
31
41
|
// Tokenise the current global filter.
|
|
32
42
|
const tokens = getTokens(table);
|
|
33
43
|
|
|
34
44
|
// If there are no tokens, return the value as-is.
|
|
35
|
-
if (tokens.length === 0)
|
|
45
|
+
if (tokens.length === 0)
|
|
46
|
+
return (
|
|
47
|
+
<Fragment>
|
|
48
|
+
{stringValue}
|
|
49
|
+
{children}
|
|
50
|
+
</Fragment>
|
|
51
|
+
);
|
|
36
52
|
|
|
37
53
|
// Create regex pattern.
|
|
38
54
|
const regex = getTokensRegex(tokens);
|
|
@@ -45,6 +61,7 @@ export const RankedCell = <
|
|
|
45
61
|
{part.match(regex) ? <mark>{part}</mark> : part}
|
|
46
62
|
</Fragment>
|
|
47
63
|
))}
|
|
64
|
+
{children}
|
|
48
65
|
</span>
|
|
49
66
|
);
|
|
50
67
|
};
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import styled from "@emotion/styled";
|
|
2
2
|
import Link from "next/link";
|
|
3
|
-
import {
|
|
3
|
+
import { PALETTE } from "../../../styles/common/constants/palette";
|
|
4
4
|
|
|
5
5
|
export const StyledNextLink = styled(Link)`
|
|
6
|
-
color: ${
|
|
6
|
+
color: ${PALETTE.INK_LIGHT};
|
|
7
7
|
margin-left: 4px;
|
|
8
8
|
opacity: 0;
|
|
9
9
|
position: absolute;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { LinkRounded } from "@mui/icons-material";
|
|
2
2
|
import { useRouter } from "next/router";
|
|
3
|
-
import React from "react";
|
|
3
|
+
import React, { MouseEvent } from "react";
|
|
4
4
|
import { StyledNextLink } from "./anchorLink.styles";
|
|
5
5
|
|
|
6
6
|
/**
|
|
@@ -13,11 +13,13 @@ import { StyledNextLink } from "./anchorLink.styles";
|
|
|
13
13
|
interface AnchorLinkProps {
|
|
14
14
|
anchorLink: string;
|
|
15
15
|
className?: string;
|
|
16
|
+
onClick?: (e: MouseEvent) => void;
|
|
16
17
|
}
|
|
17
18
|
|
|
18
19
|
export const AnchorLink = ({
|
|
19
20
|
anchorLink,
|
|
20
21
|
className,
|
|
22
|
+
onClick,
|
|
21
23
|
}: AnchorLinkProps): JSX.Element => {
|
|
22
24
|
const { query } = useRouter();
|
|
23
25
|
return (
|
|
@@ -25,6 +27,7 @@ export const AnchorLink = ({
|
|
|
25
27
|
aria-label={anchorLink}
|
|
26
28
|
className={className}
|
|
27
29
|
href={{ hash: anchorLink, query }}
|
|
30
|
+
onClick={onClick}
|
|
28
31
|
>
|
|
29
32
|
<LinkRounded fontSize="xsmall" />
|
|
30
33
|
</StyledNextLink>
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { useLayoutEffect } from "react";
|
|
2
|
+
import { CSSPropHyphen } from "./types";
|
|
3
|
+
|
|
4
|
+
export const useHtmlStyle = (
|
|
5
|
+
property: CSSPropHyphen,
|
|
6
|
+
value: string | null
|
|
7
|
+
): void => {
|
|
8
|
+
useLayoutEffect(() => {
|
|
9
|
+
// Get the HTML element.
|
|
10
|
+
const el = document.documentElement;
|
|
11
|
+
|
|
12
|
+
// Get the previous value.
|
|
13
|
+
const previousValue = el.style.getPropertyValue(property);
|
|
14
|
+
|
|
15
|
+
if (value !== null) el.style.setProperty(property, value);
|
|
16
|
+
|
|
17
|
+
return (): void => {
|
|
18
|
+
// Restore or remove property value on the HTML element.
|
|
19
|
+
if (previousValue) el.style.setProperty(property, previousValue);
|
|
20
|
+
else el.style.removeProperty(property);
|
|
21
|
+
};
|
|
22
|
+
}, [property, value]);
|
|
23
|
+
};
|