@databiosphere/findable-ui 30.0.0 → 31.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.
Files changed (89) hide show
  1. package/.release-please-manifest.json +1 -1
  2. package/CHANGELOG.md +13 -0
  3. package/lib/common/entities.d.ts +8 -26
  4. package/lib/components/DataDictionary/components/Entities/entities.d.ts +3 -1
  5. package/lib/components/DataDictionary/components/Entities/entities.js +1 -1
  6. package/lib/components/DataDictionary/components/Entities/types.d.ts +5 -5
  7. package/lib/components/DataDictionary/components/Entity/entity.d.ts +3 -1
  8. package/lib/components/DataDictionary/components/Entity/entity.js +6 -6
  9. package/lib/components/DataDictionary/components/Entity/types.d.ts +5 -5
  10. package/lib/components/DataDictionary/components/Outline/utils.d.ts +3 -2
  11. package/lib/components/DataDictionary/components/Table/hook.d.ts +3 -3
  12. package/lib/components/DataDictionary/components/Table/hook.js +3 -1
  13. package/lib/components/DataDictionary/components/Table/options/core/constants.d.ts +2 -3
  14. package/lib/components/DataDictionary/components/Table/options/hook.d.ts +2 -2
  15. package/lib/components/DataDictionary/components/Table/options/sorting/constants.d.ts +2 -3
  16. package/lib/components/DataDictionary/components/Table/table.d.ts +2 -1
  17. package/lib/components/DataDictionary/components/Table/table.js +1 -1
  18. package/lib/components/DataDictionary/components/Table/types.d.ts +3 -4
  19. package/lib/components/DataDictionary/dataDictionary.d.ts +3 -1
  20. package/lib/components/DataDictionary/hooks/UseDataDictionary/hook.d.ts +3 -1
  21. package/lib/components/DataDictionary/hooks/UseDataDictionary/types.d.ts +5 -5
  22. package/lib/components/MarkdownRenderer/components/Anchor/anchor.d.ts +19 -0
  23. package/lib/components/MarkdownRenderer/components/Anchor/anchor.js +21 -0
  24. package/lib/components/MarkdownRenderer/components/Table/table.d.ts +3 -0
  25. package/lib/components/MarkdownRenderer/components/Table/table.js +5 -0
  26. package/lib/components/MarkdownRenderer/components/Table/table.styles.d.ts +4 -0
  27. package/lib/components/MarkdownRenderer/components/Table/table.styles.js +40 -0
  28. package/lib/components/MarkdownRenderer/constants.d.ts +2 -0
  29. package/lib/components/MarkdownRenderer/constants.js +6 -0
  30. package/lib/components/MarkdownRenderer/markdownRenderer.d.ts +2 -0
  31. package/lib/components/MarkdownRenderer/markdownRenderer.js +45 -0
  32. package/lib/components/MarkdownRenderer/markdownRenderer.styles.d.ts +4 -0
  33. package/lib/components/MarkdownRenderer/markdownRenderer.styles.js +13 -0
  34. package/lib/components/MarkdownRenderer/types.d.ts +6 -0
  35. package/lib/components/MarkdownRenderer/types.js +1 -0
  36. package/lib/components/Table/components/TableCell/components/ChipCell/chipCell.d.ts +2 -1
  37. package/lib/components/Table/components/TableCell/components/ChipCell/chipCell.js +2 -2
  38. package/lib/components/Table/components/TableCell/components/LinkCell/linkCell.d.ts +1 -1
  39. package/lib/components/Table/components/TableCell/components/LinkCell/linkCell.js +2 -2
  40. package/lib/components/Table/components/TableCell/components/MarkdownCell/markdownCell.d.ts +4 -0
  41. package/lib/components/Table/components/TableCell/components/MarkdownCell/markdownCell.js +13 -0
  42. package/lib/components/Table/components/TableCell/components/MarkdownCell/markdownCell.styles.d.ts +3 -0
  43. package/lib/components/Table/components/TableCell/components/MarkdownCell/markdownCell.styles.js +30 -0
  44. package/lib/components/Table/components/TableCell/components/MarkdownCell/stories/args.d.ts +4 -0
  45. package/lib/components/Table/components/TableCell/components/MarkdownCell/stories/args.js +10 -0
  46. package/lib/components/Table/components/TableCell/components/MarkdownCell/stories/constants.d.ts +5 -0
  47. package/lib/components/Table/components/TableCell/components/MarkdownCell/stories/constants.js +9 -0
  48. package/lib/components/Table/components/TableCell/components/MarkdownCell/stories/markdownCell.stories.d.ts +7 -0
  49. package/lib/components/Table/components/TableCell/components/MarkdownCell/stories/markdownCell.stories.js +25 -0
  50. package/lib/components/Table/components/TableCell/components/MarkdownCell/stories/types.d.ts +3 -0
  51. package/lib/components/Table/components/TableCell/components/MarkdownCell/stories/types.js +1 -0
  52. package/lib/components/Table/components/TableCell/components/MarkdownCell/types.d.ts +3 -0
  53. package/lib/components/Table/components/TableCell/components/MarkdownCell/types.js +1 -0
  54. package/lib/styles/common/mui/typography.js +1 -0
  55. package/package.json +6 -1
  56. package/src/common/entities.ts +8 -31
  57. package/src/components/DataDictionary/components/Entities/entities.tsx +7 -5
  58. package/src/components/DataDictionary/components/Entities/types.ts +5 -9
  59. package/src/components/DataDictionary/components/Entity/entity.tsx +9 -7
  60. package/src/components/DataDictionary/components/Entity/types.ts +5 -9
  61. package/src/components/DataDictionary/components/Outline/utils.ts +5 -2
  62. package/src/components/DataDictionary/components/Table/hook.ts +16 -8
  63. package/src/components/DataDictionary/components/Table/options/core/constants.ts +2 -3
  64. package/src/components/DataDictionary/components/Table/options/hook.ts +3 -3
  65. package/src/components/DataDictionary/components/Table/options/sorting/constants.ts +2 -6
  66. package/src/components/DataDictionary/components/Table/table.tsx +4 -1
  67. package/src/components/DataDictionary/components/Table/types.ts +3 -4
  68. package/src/components/DataDictionary/dataDictionary.tsx +4 -2
  69. package/src/components/DataDictionary/hooks/UseDataDictionary/hook.ts +9 -2
  70. package/src/components/DataDictionary/hooks/UseDataDictionary/types.ts +5 -9
  71. package/src/components/MarkdownRenderer/components/Anchor/anchor.tsx +34 -0
  72. package/src/components/MarkdownRenderer/components/Table/table.styles.ts +41 -0
  73. package/src/components/MarkdownRenderer/components/Table/table.tsx +13 -0
  74. package/src/components/MarkdownRenderer/constants.ts +8 -0
  75. package/src/components/MarkdownRenderer/markdownRenderer.styles.ts +16 -0
  76. package/src/components/MarkdownRenderer/markdownRenderer.tsx +62 -0
  77. package/src/components/MarkdownRenderer/types.ts +7 -0
  78. package/src/components/Table/components/TableCell/components/ChipCell/chipCell.tsx +4 -2
  79. package/src/components/Table/components/TableCell/components/LinkCell/linkCell.tsx +1 -1
  80. package/src/components/Table/components/TableCell/components/MarkdownCell/markdownCell.styles.ts +31 -0
  81. package/src/components/Table/components/TableCell/components/MarkdownCell/markdownCell.tsx +29 -0
  82. package/src/components/Table/components/TableCell/components/MarkdownCell/stories/args.ts +17 -0
  83. package/src/components/Table/components/TableCell/components/MarkdownCell/stories/constants.ts +11 -0
  84. package/src/components/Table/components/TableCell/components/MarkdownCell/stories/markdownCell.stories.tsx +37 -0
  85. package/src/components/Table/components/TableCell/components/MarkdownCell/stories/types.ts +4 -0
  86. package/src/components/Table/components/TableCell/components/MarkdownCell/types.ts +3 -0
  87. package/src/styles/common/mui/typography.ts +1 -0
  88. package/tests/markdownCell.test.tsx +53 -0
  89. package/types/data-explorer-ui.d.ts +2 -0
@@ -0,0 +1,7 @@
1
+ import { Meta, StoryObj } from "@storybook/react";
2
+ import { MarkdownCell } from "../markdownCell";
3
+ declare const meta: Meta<typeof MarkdownCell>;
4
+ export default meta;
5
+ type Story = StoryObj<typeof meta>;
6
+ export declare const Default: Story;
7
+ export declare const WithHtml: Story;
@@ -0,0 +1,25 @@
1
+ import { Box } from "@mui/material";
2
+ import React from "react";
3
+ import { PALETTE } from "../../../../../../../styles/common/constants/palette";
4
+ import { MarkdownCell } from "../markdownCell";
5
+ import { DEFAULT_ARGS, WITH_HTML_ARGS } from "./args";
6
+ const meta = {
7
+ component: MarkdownCell,
8
+ decorators: [
9
+ (Story) => (React.createElement(Box, { sx: {
10
+ backgroundColor: PALETTE.COMMON_WHITE,
11
+ fontSize: "14px",
12
+ lineHeight: "20px",
13
+ padding: 3,
14
+ width: 480,
15
+ } },
16
+ React.createElement(Story, null))),
17
+ ],
18
+ };
19
+ export default meta;
20
+ export const Default = {
21
+ args: DEFAULT_ARGS,
22
+ };
23
+ export const WithHtml = {
24
+ args: WITH_HTML_ARGS,
25
+ };
@@ -0,0 +1,3 @@
1
+ import { CellContext, RowData } from "@tanstack/react-table";
2
+ import { MarkdownCellProps } from "../types";
3
+ export type GetValue = CellContext<RowData, MarkdownCellProps>["getValue"];
@@ -0,0 +1,3 @@
1
+ export type MarkdownCellProps = {
2
+ values: string;
3
+ };
@@ -1,4 +1,5 @@
1
1
  const COLOR = {
2
+ ERROR: "error",
2
3
  INHERIT: "inherit",
3
4
  INK_LIGHT: "ink.light",
4
5
  INK_MAIN: "ink.main",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@databiosphere/findable-ui",
3
- "version": "30.0.0",
3
+ "version": "31.0.0",
4
4
  "description": "",
5
5
  "scripts": {
6
6
  "test": "node --experimental-vm-modules node_modules/jest/bin/jest.js",
@@ -62,6 +62,11 @@
62
62
  "jest-fetch-mock": "^3.0.3",
63
63
  "prettier": "^2.8.3",
64
64
  "prettier-plugin-organize-imports": "^3.2.2",
65
+ "rehype-raw": "^7.0.0",
66
+ "rehype-react": "^8.0.0",
67
+ "rehype-sanitize": "^6.0.0",
68
+ "remark-gfm": "^4.0.1",
69
+ "remark-rehype": "^11.1.2",
65
70
  "storybook": "^8.6.4",
66
71
  "ts-jest": "^29.2.5",
67
72
  "typescript": "^5.5.4"
@@ -1,5 +1,4 @@
1
- import { ColumnDef } from "@tanstack/react-table";
2
- import { GridTrackSize } from "../config/entities";
1
+ import { ColumnDef, RowData } from "@tanstack/react-table";
3
2
 
4
3
  /**
5
4
  * Model of a value of a metadata class.
@@ -19,11 +18,6 @@ export interface Attribute {
19
18
  values?: string; // Free text description of attribute values
20
19
  }
21
20
 
22
- /**
23
- * Model of attribute key types; used mostly when building data dictionary column definitions.
24
- */
25
- export type AttributeValueTypes<TValue = unknown> = TValue;
26
-
27
21
  /**
28
22
  * Filterable metadata keys.
29
23
  */
@@ -41,8 +35,8 @@ export interface CategoryTag {
41
35
  /**
42
36
  * Model of a metadata class, to be specified manually or built from LinkML schema.
43
37
  */
44
- export interface Class {
45
- attributes: Attribute[];
38
+ export interface Class<T extends RowData = Attribute> {
39
+ attributes: T[];
46
40
  description: string;
47
41
  name: string; // Programmatic name or key (e.g. cell, sample)
48
42
  title: string; // Display name
@@ -62,41 +56,24 @@ export type DataDictionaryPrefix = Record<string, string>;
62
56
  /**
63
57
  * Model of a metadata dictionary containing a set of classes and their definitions.
64
58
  */
65
- export interface DataDictionary {
59
+ export interface DataDictionary<T extends RowData = Attribute> {
66
60
  annotations?: {
67
61
  [key in keyof DataDictionaryPrefix]: string; // Prefix to title e.g. "cxg": "CELLxGENE"
68
62
  };
69
- classes: Class[];
63
+ classes: Class<T>[];
70
64
  description?: string; // Free text description of data dictionary
71
65
  name: string; // Programmatic name or key (e.g. tier1, hca)
72
66
  prefixes?: DataDictionaryPrefix;
73
67
  title: string; // Display name
74
68
  }
75
69
 
76
- /**
77
- * Display model of a data dictionary column.
78
- */
79
- export interface DataDictionaryColumnDef {
80
- attributeAccessorFnName?: string; // Name of accessor function to map to.
81
- attributeCellName?: string; // Name of cell renderer component to map to.
82
- attributeDisplayName: string;
83
- attributeSlotName: string;
84
- // Adding width here for now; possibly revisit separating column def and UI.
85
- width:
86
- | Omit<GridTrackSize, "GridTrackMinMax">
87
- | {
88
- max: string;
89
- min: string;
90
- };
91
- }
92
-
93
70
  /**
94
71
  * Configuration of data dictionary; contains schema definition (that is, the actual data
95
72
  * dictionary) as well as column def for displaying the data dictionary.
96
73
  */
97
- export interface DataDictionaryConfig {
98
- columnDefs: ColumnDef<Attribute, AttributeValueTypes>[];
99
- dataDictionary: DataDictionary;
74
+ export interface DataDictionaryConfig<T extends RowData = Attribute> {
75
+ columnDefs: ColumnDef<T, T[keyof T]>[];
76
+ dataDictionary: DataDictionary<T>;
100
77
  }
101
78
 
102
79
  /**
@@ -1,20 +1,22 @@
1
1
  import { Grid } from "@mui/material";
2
+ import { RowData } from "@tanstack/react-table";
2
3
  import React from "react";
4
+ import { Attribute } from "../../../../common/entities";
3
5
  import { Entity } from "../Entity/entity";
4
6
  import { GRID_PROPS } from "./constants";
5
7
  import { ClassesProps } from "./types";
6
8
 
7
- export const Entities = ({
9
+ export const Entities = <T extends RowData = Attribute>({
8
10
  classes,
9
11
  columnDefs,
10
12
  spacing,
11
- }: ClassesProps): JSX.Element => {
13
+ }: ClassesProps<T>): JSX.Element => {
12
14
  return (
13
15
  <Grid {...GRID_PROPS}>
14
- {classes.map((classData) => (
16
+ {classes.map((cls) => (
15
17
  <Entity
16
- key={classData.name}
17
- class={classData}
18
+ key={cls.name}
19
+ class={cls}
18
20
  columnDefs={columnDefs}
19
21
  spacing={spacing}
20
22
  />
@@ -1,13 +1,9 @@
1
- import { ColumnDef } from "@tanstack/react-table";
2
- import {
3
- Attribute,
4
- AttributeValueTypes,
5
- Class,
6
- } from "../../../../common/entities";
1
+ import { ColumnDef, RowData } from "@tanstack/react-table";
2
+ import { Attribute, Class } from "../../../../common/entities";
7
3
  import { LayoutSpacing } from "../../hooks/UseLayoutSpacing/types";
8
4
 
9
- export interface ClassesProps {
10
- classes: Class[];
11
- columnDefs: ColumnDef<Attribute, AttributeValueTypes>[];
5
+ export interface ClassesProps<T extends RowData = Attribute> {
6
+ classes: Class<T>[];
7
+ columnDefs: ColumnDef<T, T[keyof T]>[];
12
8
  spacing?: LayoutSpacing;
13
9
  }
@@ -1,5 +1,7 @@
1
1
  import { Grid, Typography } from "@mui/material";
2
+ import { RowData } from "@tanstack/react-table";
2
3
  import React from "react";
4
+ import { Attribute } from "../../../../common/entities";
3
5
  import { TYPOGRAPHY_PROPS } from "../../../../styles/common/mui/typography";
4
6
  import { AnchorLink } from "../../../common/AnchorLink/anchorLink";
5
7
  import { useTable } from "../Table/hook";
@@ -8,29 +10,29 @@ import { GRID_PROPS } from "./constants";
8
10
  import { StyledTypography } from "./entity.styles";
9
11
  import { EntityProps } from "./types";
10
12
 
11
- export const Entity = ({
12
- class: classData,
13
+ export const Entity = <T extends RowData = Attribute>({
14
+ class: cls,
13
15
  columnDefs,
14
16
  spacing,
15
- }: EntityProps): JSX.Element => {
16
- const table = useTable(classData.attributes, columnDefs);
17
+ }: EntityProps<T>): JSX.Element => {
18
+ const table = useTable<T>(cls.attributes, columnDefs);
17
19
  return (
18
20
  <Grid {...GRID_PROPS} rowGap={4}>
19
21
  <Grid {...GRID_PROPS} rowGap={1}>
20
22
  <StyledTypography
21
23
  component="h3"
22
- id={classData.name}
24
+ id={cls.name}
23
25
  variant={TYPOGRAPHY_PROPS.VARIANT.TEXT_HEADING_SMALL}
24
26
  {...spacing}
25
27
  >
26
- {classData.title} <AnchorLink anchorLink={classData.name} />
28
+ {cls.title} <AnchorLink anchorLink={cls.name} />
27
29
  </StyledTypography>
28
30
  <Typography
29
31
  color={TYPOGRAPHY_PROPS.COLOR.INK_LIGHT}
30
32
  component="div"
31
33
  variant={TYPOGRAPHY_PROPS.VARIANT.TEXT_BODY_400_2_LINES}
32
34
  >
33
- {classData.description}
35
+ {cls.description}
34
36
  </Typography>
35
37
  </Grid>
36
38
  <Table table={table} />
@@ -1,13 +1,9 @@
1
- import { ColumnDef } from "@tanstack/react-table";
2
- import {
3
- Attribute,
4
- AttributeValueTypes,
5
- Class,
6
- } from "../../../../common/entities";
1
+ import { ColumnDef, RowData } from "@tanstack/react-table";
2
+ import { Attribute, Class } from "../../../../common/entities";
7
3
  import { LayoutSpacing } from "../../hooks/UseLayoutSpacing/types";
8
4
 
9
- export interface EntityProps {
10
- class: Class;
11
- columnDefs: ColumnDef<Attribute, AttributeValueTypes>[];
5
+ export interface EntityProps<T extends RowData = Attribute> {
6
+ class: Class<T>;
7
+ columnDefs: ColumnDef<T, T[keyof T]>[];
12
8
  spacing?: LayoutSpacing;
13
9
  }
@@ -1,4 +1,5 @@
1
- import { Class } from "../../../../common/entities";
1
+ import { RowData } from "@tanstack/react-table";
2
+ import { Attribute, Class } from "../../../../common/entities";
2
3
  import { OutlineItem } from "../../../Layout/components/Outline/types";
3
4
 
4
5
  /**
@@ -6,7 +7,9 @@ import { OutlineItem } from "../../../Layout/components/Outline/types";
6
7
  * @param classes - Class entities.
7
8
  * @returns Outline items.
8
9
  */
9
- export function buildClassesOutline(classes: Class[]): OutlineItem[] {
10
+ export function buildClassesOutline<T extends RowData = Attribute>(
11
+ classes: Class<T>[]
12
+ ): OutlineItem[] {
10
13
  return classes.map(({ name, title }) => {
11
14
  return {
12
15
  depth: 2,
@@ -1,13 +1,21 @@
1
- import { ColumnDef, Table, useReactTable } from "@tanstack/react-table";
2
- import { Attribute, AttributeValueTypes } from "../../../../common/entities";
1
+ import {
2
+ ColumnDef,
3
+ RowData,
4
+ Table,
5
+ useReactTable,
6
+ } from "@tanstack/react-table";
7
+ import { Attribute } from "../../../../common/entities";
3
8
  import { useTableOptions } from "./options/hook";
4
9
 
5
- export const useTable = (
6
- data: Attribute[],
7
- columnDefs: ColumnDef<Attribute, AttributeValueTypes>[]
8
- ): Table<Attribute> => {
9
- const tableOptions = useTableOptions();
10
- return useReactTable<Attribute>({
10
+ export const useTable = <T extends RowData = Attribute>(
11
+ data: T[],
12
+ columnDefs: ColumnDef<T, T[keyof T]>[]
13
+ ): Table<T> => {
14
+ // Table options.
15
+ const tableOptions = useTableOptions<T>();
16
+
17
+ // Table instance.
18
+ return useReactTable<T>({
11
19
  ...tableOptions,
12
20
  columns: columnDefs,
13
21
  data,
@@ -1,10 +1,9 @@
1
- import { CoreOptions, getCoreRowModel } from "@tanstack/react-table";
2
- import { Attribute } from "../../../../../../common/entities";
1
+ import { CoreOptions, getCoreRowModel, RowData } from "@tanstack/react-table";
3
2
  import { ROW_POSITION } from "../../../../../Table/features/RowPosition/constants";
4
3
  import { ROW_PREVIEW } from "../../../../../Table/features/RowPreview/constants";
5
4
 
6
5
  export const CORE_OPTIONS: Pick<
7
- CoreOptions<Attribute>,
6
+ CoreOptions<RowData>,
8
7
  "_features" | "getCoreRowModel"
9
8
  > = {
10
9
  _features: [ROW_POSITION, ROW_PREVIEW],
@@ -1,10 +1,10 @@
1
- import { TableOptions } from "@tanstack/react-table";
1
+ import { RowData, TableOptions } from "@tanstack/react-table";
2
2
  import { Attribute } from "../../../../../common/entities";
3
3
  import { CORE_OPTIONS } from "./core/constants";
4
4
  import { SORTING_OPTIONS } from "./sorting/constants";
5
5
 
6
- export const useTableOptions = (): Omit<
7
- TableOptions<Attribute>,
6
+ export const useTableOptions = <T extends RowData = Attribute>(): Omit<
7
+ TableOptions<T>,
8
8
  "columns" | "data"
9
9
  > => {
10
10
  return {
@@ -1,9 +1,5 @@
1
- import { SortingOptions } from "@tanstack/react-table";
2
- import { Attribute } from "../../../../../../common/entities";
1
+ import { RowData, SortingOptions } from "@tanstack/react-table";
3
2
 
4
- export const SORTING_OPTIONS: Pick<
5
- SortingOptions<Attribute>,
6
- "enableSorting"
7
- > = {
3
+ export const SORTING_OPTIONS: Pick<SortingOptions<RowData>, "enableSorting"> = {
8
4
  enableSorting: false,
9
5
  };
@@ -1,4 +1,5 @@
1
1
  import { TableContainer } from "@mui/material";
2
+ import { RowData } from "@tanstack/react-table";
2
3
  import React from "react";
3
4
  import { TableBody } from "../../../Detail/components/Table/components/TableBody/tableBody";
4
5
  import { ROW_DIRECTION } from "../../../Table/common/entities";
@@ -9,7 +10,9 @@ import { GridPaper } from "../../../common/Paper/paper.styles";
9
10
  import { StyledRoundedPaper } from "./table.styles";
10
11
  import { TableProps } from "./types";
11
12
 
12
- export const Table = ({ table }: TableProps): JSX.Element => {
13
+ export const Table = <T extends RowData>({
14
+ table,
15
+ }: TableProps<T>): JSX.Element => {
13
16
  return (
14
17
  <StyledRoundedPaper variant="table">
15
18
  <GridPaper>
@@ -1,6 +1,5 @@
1
- import { Table } from "@tanstack/react-table";
2
- import { Attribute } from "../../../../common/entities";
1
+ import { RowData, Table } from "@tanstack/react-table";
3
2
 
4
- export interface TableProps {
5
- table: Table<Attribute>;
3
+ export interface TableProps<T extends RowData> {
4
+ table: Table<T>;
6
5
  }
@@ -1,4 +1,6 @@
1
+ import { RowData } from "@tanstack/react-table";
1
2
  import React, { useMemo } from "react";
3
+ import { Attribute } from "../../common/entities";
2
4
  import { Entities } from "./components/Entities/entities";
3
5
  import { EntitiesLayout as DefaultEntitiesLayout } from "./components/Layout/components/EntitiesLayout/entitiesLayout";
4
6
  import { OutlineLayout as DefaultOutlineLayout } from "./components/Layout/components/OutlineLayout/outlineLayout";
@@ -11,7 +13,7 @@ import { useDataDictionary } from "./hooks/UseDataDictionary/hook";
11
13
  import { useLayoutSpacing } from "./hooks/UseLayoutSpacing/hook";
12
14
  import { DataDictionaryProps } from "./types";
13
15
 
14
- export const DataDictionary = ({
16
+ export const DataDictionary = <T extends RowData = Attribute>({
15
17
  className,
16
18
  EntitiesLayout = DefaultEntitiesLayout,
17
19
  Outline = DefaultOutline,
@@ -19,7 +21,7 @@ export const DataDictionary = ({
19
21
  Title = DefaultTitle,
20
22
  TitleLayout = DefaultTitleLayout,
21
23
  }: DataDictionaryProps): JSX.Element => {
22
- const { classes, columnDefs } = useDataDictionary();
24
+ const { classes, columnDefs } = useDataDictionary<T>();
23
25
  const { spacing } = useLayoutSpacing();
24
26
  const outline = useMemo(() => buildClassesOutline(classes), [classes]);
25
27
  return (
@@ -1,13 +1,20 @@
1
+ import { RowData } from "@tanstack/react-table";
1
2
  import { useMemo } from "react";
3
+ import { Attribute, DataDictionaryConfig } from "../../../../common/entities";
2
4
  import { useConfig } from "../../../../hooks/useConfig";
3
5
  import { UseDataDictionary } from "./types";
4
6
 
5
- export const useDataDictionary = (): UseDataDictionary => {
7
+ export const useDataDictionary = <
8
+ T extends RowData = Attribute
9
+ >(): UseDataDictionary<T> => {
6
10
  const {
7
11
  config: { dataDictionaries: dataDictionaryConfigs },
8
12
  } = useConfig();
9
13
 
10
- const dataDictionaryConfig = dataDictionaryConfigs?.[0]; // TODO: Handle multiple data dictionaries
14
+ const dataDictionaryConfig = dataDictionaryConfigs?.[0] as
15
+ | DataDictionaryConfig<T>
16
+ | undefined; // TODO: Handle multiple data dictionaries
17
+
11
18
  return useMemo(() => {
12
19
  const classes = dataDictionaryConfig?.dataDictionary?.classes || [];
13
20
  const columnDefs = dataDictionaryConfig?.columnDefs || [];
@@ -1,11 +1,7 @@
1
- import { ColumnDef } from "@tanstack/react-table";
2
- import {
3
- Attribute,
4
- AttributeValueTypes,
5
- Class,
6
- } from "../../../../common/entities";
1
+ import { ColumnDef, RowData } from "@tanstack/react-table";
2
+ import { Attribute, Class } from "../../../../common/entities";
7
3
 
8
- export interface UseDataDictionary {
9
- classes: Class[];
10
- columnDefs: ColumnDef<Attribute, AttributeValueTypes>[];
4
+ export interface UseDataDictionary<T extends RowData = Attribute> {
5
+ classes: Class<T>[];
6
+ columnDefs: ColumnDef<T, T[keyof T]>[];
11
7
  }
@@ -0,0 +1,34 @@
1
+ import React, { AnchorHTMLAttributes, ClassAttributes } from "react";
2
+ import { Link } from "../../../Links/components/Link/link";
3
+ import { BaseComponentProps } from "../../../types";
4
+
5
+ /**
6
+ * rehype-sanitize's default schema allows only a limited set of attributes on <a> elements:
7
+ * - aria-*
8
+ * - className
9
+ * - data-footnote-backref
10
+ * - data-footnote-ref
11
+ * - href
12
+ *
13
+ * By default, attributes such as:
14
+ * - download
15
+ * - rel
16
+ * - target
17
+ * are not permitted and will be stripped from anchor tags during sanitization.
18
+ *
19
+ * Note: This component currently does not support these excluded attributes.
20
+ */
21
+
22
+ export const Anchor = (
23
+ props: BaseComponentProps &
24
+ ClassAttributes<HTMLAnchorElement> &
25
+ AnchorHTMLAttributes<HTMLAnchorElement>
26
+ ): JSX.Element => {
27
+ return (
28
+ <Link
29
+ className={props.className}
30
+ label={props.children}
31
+ url={props.href || ""}
32
+ />
33
+ );
34
+ };
@@ -0,0 +1,41 @@
1
+ import styled from "@emotion/styled";
2
+ import { PALETTE } from "../../../../styles/common/constants/palette";
3
+ import { textBody500 } from "../../../../styles/common/mixins/fonts";
4
+
5
+ export const StyledTable = styled("table")`
6
+ border-collapse: collapse;
7
+ margin: 16px 0;
8
+ table-layout: fixed;
9
+ width: 100%;
10
+
11
+ thead {
12
+ all: unset;
13
+ display: table-header-group;
14
+ }
15
+
16
+ tbody {
17
+ all: unset;
18
+ display: table-row-group;
19
+ }
20
+
21
+ tr {
22
+ all: unset;
23
+ display: table-row;
24
+ }
25
+
26
+ td,
27
+ th {
28
+ display: table-cell;
29
+ padding: 2px 4px;
30
+ }
31
+
32
+ th {
33
+ ${textBody500}
34
+ border-bottom: 1px solid ${PALETTE.SMOKE_MAIN};
35
+ }
36
+
37
+ td {
38
+ font: inherit;
39
+ overflow-wrap: break-word;
40
+ }
41
+ `;
@@ -0,0 +1,13 @@
1
+ import { BaseComponentProps } from "components/types";
2
+ import React, { ClassAttributes, TableHTMLAttributes } from "react";
3
+ import { StyledTable } from "./table.styles";
4
+
5
+ export const Table = (
6
+ props: BaseComponentProps &
7
+ ClassAttributes<HTMLTableElement> &
8
+ TableHTMLAttributes<HTMLTableElement>
9
+ ): JSX.Element => {
10
+ return (
11
+ <StyledTable className={props.className}>{props.children}</StyledTable>
12
+ );
13
+ };
@@ -0,0 +1,8 @@
1
+ import { Components } from "rehype-react";
2
+ import { Anchor } from "./components/Anchor/anchor";
3
+ import { Table } from "./components/Table/table";
4
+
5
+ export const COMPONENTS: Partial<Components> = {
6
+ a: Anchor,
7
+ table: Table,
8
+ };
@@ -0,0 +1,16 @@
1
+ import styled from "@emotion/styled";
2
+
3
+ // See https://github.com/emotion-js/emotion/issues/1105.
4
+ // See https://github.com/emotion-js/emotion/releases/tag/%40emotion%2Fcache%4011.10.2.
5
+ const ignoreSsrWarning =
6
+ "/* emotion-disable-server-rendering-unsafe-selector-warning-please-do-not-use-this-the-warning-exists-for-a-reason */";
7
+
8
+ export const StyledContainer = styled("div")`
9
+ > *:first-child:not(style)${ignoreSsrWarning} {
10
+ margin-top: 0;
11
+ }
12
+
13
+ > *:last-child:not(style)${ignoreSsrWarning} {
14
+ margin-bottom: 0;
15
+ }
16
+ `;
@@ -0,0 +1,62 @@
1
+ import { Typography } from "@mui/material";
2
+ import React, { useEffect, useState } from "react";
3
+ import * as production from "react/jsx-runtime";
4
+ import rehypeRaw from "rehype-raw";
5
+ import rehypeReact, { Components } from "rehype-react";
6
+ import rehypeSanitize, { defaultSchema } from "rehype-sanitize";
7
+ import remarkGfm from "remark-gfm";
8
+ import remarkParse from "remark-parse";
9
+ import remarkRehype from "remark-rehype";
10
+ import { unified } from "unified";
11
+ import { TYPOGRAPHY_PROPS } from "../../styles/common/mui/typography";
12
+ import { COMPONENTS } from "./constants";
13
+ import { StyledContainer } from "./markdownRenderer.styles";
14
+ import { MarkdownRendererProps } from "./types";
15
+
16
+ export const MarkdownRenderer = ({
17
+ className,
18
+ components = COMPONENTS,
19
+ value,
20
+ }: MarkdownRendererProps): JSX.Element => {
21
+ const [element, setElement] = useState<JSX.Element | null>(null);
22
+ const [error, setError] = useState<string | null>(null);
23
+ const [componentOptions] = useState<Partial<Components>>(components);
24
+
25
+ useEffect(() => {
26
+ let cancelled = false;
27
+ setError(null);
28
+
29
+ const processor = unified()
30
+ .use(remarkParse)
31
+ .use(remarkGfm)
32
+ .use(remarkRehype, { allowDangerousHtml: true })
33
+ .use(rehypeRaw)
34
+ .use(rehypeSanitize, defaultSchema)
35
+ .use(rehypeReact, { ...production, components: componentOptions });
36
+
37
+ processor
38
+ .process(value)
39
+ .then((file) => {
40
+ if (!cancelled) setElement(file?.result);
41
+ })
42
+ .catch((err) => {
43
+ if (!cancelled) setError(err.message);
44
+ });
45
+
46
+ return (): void => {
47
+ cancelled = true;
48
+ };
49
+ }, [componentOptions, value]);
50
+
51
+ if (error)
52
+ return (
53
+ <Typography
54
+ color={TYPOGRAPHY_PROPS.COLOR.ERROR}
55
+ variant={TYPOGRAPHY_PROPS.VARIANT.TEXT_BODY_SMALL_400}
56
+ >
57
+ {error}
58
+ </Typography>
59
+ );
60
+
61
+ return <StyledContainer className={className}>{element}</StyledContainer>;
62
+ };
@@ -0,0 +1,7 @@
1
+ import { Components } from "rehype-react";
2
+ import { BaseComponentProps } from "../types";
3
+
4
+ export interface MarkdownRendererProps extends BaseComponentProps {
5
+ components?: Partial<Components>;
6
+ value: string;
7
+ }