@databiosphere/findable-ui 39.0.0 → 39.1.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.
Files changed (47) hide show
  1. package/.release-please-manifest.json +1 -1
  2. package/CHANGELOG.md +7 -0
  3. package/lib/components/DataDictionary/components/Entities/entities.d.ts +1 -1
  4. package/lib/components/DataDictionary/components/Entities/entities.js +2 -2
  5. package/lib/components/DataDictionary/components/Entities/types.d.ts +0 -2
  6. package/lib/components/DataDictionary/components/Entity/entity.d.ts +1 -1
  7. package/lib/components/DataDictionary/components/Entity/entity.js +3 -3
  8. package/lib/components/DataDictionary/components/Entity/entity.styles.js +0 -2
  9. package/lib/components/DataDictionary/components/Entity/types.d.ts +0 -2
  10. package/lib/components/DataDictionary/components/Table/table.js +6 -8
  11. package/lib/components/DataDictionary/components/Table/table.styles.d.ts +7 -0
  12. package/lib/components/DataDictionary/components/Table/table.styles.js +8 -0
  13. package/lib/components/DataDictionary/dataDictionary.js +6 -1
  14. package/lib/components/Detail/components/Table/components/TableRows/components/CollapsableRows/collapsableRows.js +1 -1
  15. package/lib/components/Detail/components/Table/components/TableRows/tableRows.js +1 -1
  16. package/lib/components/Index/index.styles.js +3 -1
  17. package/lib/components/Table/components/TableCell/components/MarkdownCell/markdownCell.d.ts +1 -1
  18. package/lib/components/Table/components/TableCell/components/RankedCell/rankedCell.d.ts +2 -2
  19. package/lib/components/Table/components/TableCell/components/RankedCell/rankedCell.js +12 -4
  20. package/lib/components/common/AnchorLink/anchorLink.d.ts +3 -1
  21. package/lib/components/common/AnchorLink/anchorLink.js +2 -2
  22. package/lib/components/common/AnchorLink/anchorLink.styles.js +2 -2
  23. package/lib/hooks/useHtmlStyle/constants.d.ts +2 -0
  24. package/lib/hooks/useHtmlStyle/constants.js +3 -0
  25. package/lib/hooks/useHtmlStyle/hook.d.ts +2 -0
  26. package/lib/hooks/useHtmlStyle/hook.js +18 -0
  27. package/lib/hooks/useHtmlStyle/types.d.ts +2 -0
  28. package/lib/hooks/useHtmlStyle/types.js +1 -0
  29. package/package.json +1 -1
  30. package/src/components/DataDictionary/components/Entities/entities.tsx +1 -2
  31. package/src/components/DataDictionary/components/Entities/types.ts +0 -2
  32. package/src/components/DataDictionary/components/Entity/entity.styles.ts +1 -4
  33. package/src/components/DataDictionary/components/Entity/entity.tsx +9 -9
  34. package/src/components/DataDictionary/components/Entity/types.ts +0 -2
  35. package/src/components/DataDictionary/components/Table/table.styles.ts +9 -0
  36. package/src/components/DataDictionary/components/Table/table.tsx +17 -20
  37. package/src/components/DataDictionary/dataDictionary.tsx +7 -1
  38. package/src/components/Detail/components/Table/components/TableRows/components/CollapsableRows/collapsableRows.tsx +5 -1
  39. package/src/components/Detail/components/Table/components/TableRows/tableRows.tsx +1 -0
  40. package/src/components/Index/index.styles.ts +3 -1
  41. package/src/components/Table/components/TableCell/components/MarkdownCell/markdownCell.tsx +1 -1
  42. package/src/components/Table/components/TableCell/components/RankedCell/rankedCell.tsx +21 -4
  43. package/src/components/common/AnchorLink/anchorLink.styles.ts +2 -2
  44. package/src/components/common/AnchorLink/anchorLink.tsx +4 -1
  45. package/src/hooks/useHtmlStyle/constants.ts +5 -0
  46. package/src/hooks/useHtmlStyle/hook.ts +23 -0
  47. package/src/hooks/useHtmlStyle/types.ts +3 -0
@@ -1,3 +1,3 @@
1
1
  {
2
- ".": "39.0.0"
2
+ ".": "39.1.0"
3
3
  }
package/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # Changelog
2
2
 
3
+ ## [39.1.0](https://github.com/DataBiosphere/findable-ui/compare/v39.0.0...v39.1.0) (2025-07-24)
4
+
5
+
6
+ ### Features
7
+
8
+ * 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))
9
+
3
10
  ## [39.0.0](https://github.com/DataBiosphere/findable-ui/compare/v38.3.0...v39.0.0) (2025-07-23)
4
11
 
5
12
 
@@ -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>({ spacing, table, }: ClassesProps<T>) => JSX.Element;
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 = ({ spacing, table, }) => {
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, spacing: spacing, table: table })))));
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, spacing, table, }: EntityProps<T>) => JSX.Element | null;
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, spacing, table, }) => {
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, ...spacing },
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 styled from "@emotion/styled";
2
2
  import { Typography } from "@mui/material";
3
3
  export const StyledTypography = styled(Typography) `
4
- scroll-margin-top: ${({ top = 0 }) => top}px;
5
-
6
4
  &:hover a {
7
5
  opacity: 1;
8
6
  }
@@ -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 { RoundedPaper } from "../../../common/Paper/components/RoundedPaper/roundedPaper";
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(RoundedPaper, { elevation: 0 },
12
- React.createElement(GridPaper, null,
13
- React.createElement(TableContainer, null,
14
- React.createElement(GridTable, { gridTemplateColumns: getColumnTrackSizing(table.getVisibleFlatColumns()) },
15
- React.createElement(TableHead, { tableInstance: table }),
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, { spacing: entitiesSpacing, table: table }))))));
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;
@@ -1,3 +1,3 @@
1
1
  import { CellContext, RowData } from "@tanstack/react-table";
2
- import { BaseComponentProps } from "components/types";
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 = ({ className, column, getValue, row, table, }) => {
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, stringValue);
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, stringValue);
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 }, stringValue.split(regex).map((part, i) => (React.createElement(Fragment, { key: i }, part.match(regex) ? React.createElement("mark", null, part) : part)))));
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 { inkLight } from "../../../styles/common/mixins/colors";
3
+ import { PALETTE } from "../../../styles/common/constants/palette";
4
4
  export const StyledNextLink = styled(Link) `
5
- color: ${inkLight};
5
+ color: ${PALETTE.INK_LIGHT};
6
6
  margin-left: 4px;
7
7
  opacity: 0;
8
8
  position: absolute;
@@ -0,0 +1,2 @@
1
+ import { CSSPropHyphen } from "./types";
2
+ export declare const PROPERTY: Record<string, CSSPropHyphen>;
@@ -0,0 +1,3 @@
1
+ export const PROPERTY = {
2
+ SCROLL_PADDING_TOP: "scroll-padding-top",
3
+ };
@@ -0,0 +1,2 @@
1
+ import { CSSPropHyphen } from "./types";
2
+ export declare const useHtmlStyle: (property: CSSPropHyphen, value: string | null) => void;
@@ -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,2 @@
1
+ import type * as CSS from "csstype";
2
+ export type CSSPropHyphen = keyof CSS.PropertiesHyphen;
@@ -0,0 +1 @@
1
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@databiosphere/findable-ui",
3
- "version": "39.0.0",
3
+ "version": "39.1.0",
4
4
  "description": "",
5
5
  "scripts": {
6
6
  "test": "node --experimental-vm-modules node_modules/jest/bin/jest.js",
@@ -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} spacing={spacing} table={table} />
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
- <Typography
40
- color={TYPOGRAPHY_PROPS.COLOR.INK_LIGHT}
41
- component="div"
42
- variant={TYPOGRAPHY_PROPS.VARIANT.TEXT_BODY_400_2_LINES}
43
- >
44
- {cls.description}
45
- </Typography>
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 { RoundedPaper } from "../../../common/Paper/components/RoundedPaper/roundedPaper";
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
- <RoundedPaper elevation={0}>
19
- <GridPaper>
20
- <TableContainer>
21
- <GridTable
22
- gridTemplateColumns={getColumnTrackSizing(
23
- table.getVisibleFlatColumns()
24
- )}
25
- >
26
- <TableHead tableInstance={table} />
27
- <TableBody
28
- rowDirection={ROW_DIRECTION.DEFAULT}
29
- rows={row.getLeafRows()}
30
- tableInstance={table}
31
- />
32
- </GridTable>
33
- </TableContainer>
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 spacing={entitiesSpacing} table={table} />
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 key={row.id} isPreview={row.getIsPreview()}>
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}
@@ -35,6 +35,7 @@ export const TableRows = <T extends RowData>({
35
35
  return (
36
36
  <StyledTableRow
37
37
  key={row.id}
38
+ id={row.id}
38
39
  canExpand={row.getCanExpand()}
39
40
  isExpanded={row.getIsExpanded()}
40
41
  isGrouped={row.getIsGrouped()}
@@ -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)<LayoutSpacing>`
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;
@@ -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 & CellContext<T, TValue>): JSX.Element | null => {
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) return <Fragment>{stringValue}</Fragment>;
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) return <Fragment>{stringValue}</Fragment>;
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 { inkLight } from "../../../styles/common/mixins/colors";
3
+ import { PALETTE } from "../../../styles/common/constants/palette";
4
4
 
5
5
  export const StyledNextLink = styled(Link)`
6
- color: ${inkLight};
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,5 @@
1
+ import { CSSPropHyphen } from "./types";
2
+
3
+ export const PROPERTY: Record<string, CSSPropHyphen> = {
4
+ SCROLL_PADDING_TOP: "scroll-padding-top",
5
+ };
@@ -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
+ };
@@ -0,0 +1,3 @@
1
+ import type * as CSS from "csstype";
2
+
3
+ export type CSSPropHyphen = keyof CSS.PropertiesHyphen;