@databiosphere/findable-ui 38.1.0 → 38.2.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 +19 -0
- package/lib/components/DataDictionary/components/Description/description.d.ts +2 -0
- package/lib/components/DataDictionary/components/Description/description.js +8 -0
- package/lib/components/DataDictionary/components/Description/description.styles.d.ts +10 -0
- package/lib/components/DataDictionary/components/Description/description.styles.js +51 -0
- package/lib/components/DataDictionary/components/Description/types.d.ts +3 -0
- package/lib/components/DataDictionary/components/Description/types.js +1 -0
- package/lib/components/DataDictionary/components/Layout/components/EntitiesLayout/entitiesLayout.styles.js +2 -0
- package/lib/components/DataDictionary/dataDictionary.js +3 -1
- package/lib/components/DataDictionary/hooks/UseDataDictionaryConfig/hook.js +1 -0
- package/lib/components/DataDictionary/hooks/UseDataDictionaryConfig/types.d.ts +1 -0
- package/lib/components/Filter/components/FilterRange/filterRange.styles.js +1 -0
- package/lib/components/Table/components/TableBody/tableBody.d.ts +3 -3
- package/lib/components/Table/components/TableBody/tableBody.js +2 -12
- package/lib/components/Table/hooks/UseVirtualization/hook.d.ts +7 -0
- package/lib/components/Table/hooks/UseVirtualization/hook.js +18 -0
- package/lib/components/Table/hooks/UseVirtualization/types.d.ts +8 -0
- package/lib/components/Table/hooks/UseVirtualization/types.js +1 -0
- package/lib/components/Table/{components/TableBody → hooks/UseVirtualization}/utils.d.ts +1 -3
- package/lib/components/Table/{components/TableBody → hooks/UseVirtualization}/utils.js +8 -4
- package/lib/components/Table/table.js +13 -14
- package/package.json +1 -1
- package/src/components/DataDictionary/components/Description/description.styles.ts +56 -0
- package/src/components/DataDictionary/components/Description/description.tsx +17 -0
- package/src/components/DataDictionary/components/Description/types.ts +3 -0
- package/src/components/DataDictionary/components/Layout/components/EntitiesLayout/entitiesLayout.styles.ts +2 -0
- package/src/components/DataDictionary/dataDictionary.tsx +3 -1
- package/src/components/DataDictionary/hooks/UseDataDictionaryConfig/hook.ts +1 -0
- package/src/components/DataDictionary/hooks/UseDataDictionaryConfig/types.ts +1 -0
- package/src/components/Filter/components/FilterRange/filterRange.styles.ts +1 -0
- package/src/components/Table/components/TableBody/tableBody.tsx +6 -19
- package/src/components/Table/hooks/UseVirtualization/hook.ts +31 -0
- package/src/components/Table/hooks/UseVirtualization/types.ts +9 -0
- package/src/components/Table/{components/TableBody → hooks/UseVirtualization}/utils.ts +11 -5
- package/src/components/Table/table.tsx +12 -14
- package/lib/hooks/useScroll.d.ts +0 -10
- package/lib/hooks/useScroll.js +0 -12
- package/src/hooks/useScroll.ts +0 -21
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [38.2.0](https://github.com/DataBiosphere/findable-ui/compare/v38.1.1...v38.2.0) (2025-07-11)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* add 'introduction' section to data dictionary ([#566](https://github.com/DataBiosphere/findable-ui/issues/566)) ([#567](https://github.com/DataBiosphere/findable-ui/issues/567)) ([5aeb758](https://github.com/DataBiosphere/findable-ui/commit/5aeb758792532a78fa4ec71dc0f7b3ad8c80c376))
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Bug Fixes
|
|
12
|
+
|
|
13
|
+
* align range filter toggle button styles with design ([#563](https://github.com/DataBiosphere/findable-ui/issues/563)) ([#564](https://github.com/DataBiosphere/findable-ui/issues/564)) ([1cc1ffd](https://github.com/DataBiosphere/findable-ui/commit/1cc1ffd88ae3b2f436717b494e425614412cface))
|
|
14
|
+
|
|
15
|
+
## [38.1.1](https://github.com/DataBiosphere/findable-ui/compare/v38.1.0...v38.1.1) (2025-07-09)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
### Bug Fixes
|
|
19
|
+
|
|
20
|
+
* table view fails to render after switching from graph view ([#560](https://github.com/DataBiosphere/findable-ui/issues/560)) ([#561](https://github.com/DataBiosphere/findable-ui/issues/561)) ([35a2f0c](https://github.com/DataBiosphere/findable-ui/commit/35a2f0c84119f66c372750442c8b29ca93af9057))
|
|
21
|
+
|
|
3
22
|
## [38.1.0](https://github.com/DataBiosphere/findable-ui/compare/v38.0.0...v38.1.0) (2025-07-09)
|
|
4
23
|
|
|
5
24
|
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { StyledMarkdownRenderer, StyledRoundedPaper, } from "./description.styles";
|
|
3
|
+
export const Description = ({ description, }) => {
|
|
4
|
+
if (!description)
|
|
5
|
+
return null;
|
|
6
|
+
return (React.createElement(StyledRoundedPaper, { elevation: 0 },
|
|
7
|
+
React.createElement(StyledMarkdownRenderer, { value: description })));
|
|
8
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
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
|
+
}, {}, {}>;
|
|
8
|
+
export declare const StyledMarkdownRenderer: import("@emotion/styled").StyledComponent<import("../../../MarkdownRenderer/types").MarkdownRendererProps & {
|
|
9
|
+
theme?: import("@emotion/react").Theme;
|
|
10
|
+
}, {}, {}>;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import styled from "@emotion/styled";
|
|
2
|
+
import { PALETTE } from "../../../../styles/common/constants/palette";
|
|
3
|
+
import { mediaTabletDown, mediaTabletUp, } from "../../../../styles/common/mixins/breakpoints";
|
|
4
|
+
import { textHeadingSmall } from "../../../../styles/common/mixins/fonts";
|
|
5
|
+
import { RoundedPaper } from "../../../common/Paper/components/RoundedPaper/roundedPaper";
|
|
6
|
+
import { MarkdownRenderer } from "../../../MarkdownRenderer/markdownRenderer";
|
|
7
|
+
export const StyledRoundedPaper = styled(RoundedPaper) `
|
|
8
|
+
padding: 20px;
|
|
9
|
+
|
|
10
|
+
${mediaTabletDown} {
|
|
11
|
+
padding: 20px 16px;
|
|
12
|
+
}
|
|
13
|
+
`;
|
|
14
|
+
export const StyledMarkdownRenderer = styled(MarkdownRenderer) `
|
|
15
|
+
align-self: flex-start;
|
|
16
|
+
|
|
17
|
+
code {
|
|
18
|
+
all: unset;
|
|
19
|
+
font: inherit;
|
|
20
|
+
font-family: Roboto Mono, monospace;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
h2,
|
|
24
|
+
h3,
|
|
25
|
+
h4,
|
|
26
|
+
h5,
|
|
27
|
+
h6 {
|
|
28
|
+
margin: 8px 0;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
h2 {
|
|
32
|
+
${textHeadingSmall};
|
|
33
|
+
font-size: 18px;
|
|
34
|
+
line-height: 26px;
|
|
35
|
+
|
|
36
|
+
${mediaTabletUp} {
|
|
37
|
+
font-size: 18px;
|
|
38
|
+
line-height: 26px;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
hr {
|
|
43
|
+
border: none;
|
|
44
|
+
border-bottom: 1px solid ${PALETTE.SMOKE_MAIN};
|
|
45
|
+
margin: 16px 0;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
p {
|
|
49
|
+
font: inherit;
|
|
50
|
+
}
|
|
51
|
+
`;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -4,6 +4,8 @@ import { LAYOUT_SPACING } from "../../constants";
|
|
|
4
4
|
const PB = LAYOUT_SPACING.CONTENT_PADDING_BOTTOM; /* bottom padding */
|
|
5
5
|
const PT = LAYOUT_SPACING.CONTENT_PADDING_TOP; /* top padding */
|
|
6
6
|
export const Layout = styled("div") `
|
|
7
|
+
display: grid;
|
|
8
|
+
gap: 16px;
|
|
7
9
|
grid-column: 2;
|
|
8
10
|
grid-row: 1;
|
|
9
11
|
padding-bottom: ${PB}px;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Fade } from "@mui/material";
|
|
2
2
|
import React from "react";
|
|
3
3
|
import { useLayoutSpacing } from "../../hooks/UseLayoutSpacing/hook";
|
|
4
|
+
import { Description } from "./components/Description/description";
|
|
4
5
|
import { Entities } from "./components/Entities/entities";
|
|
5
6
|
import { ColumnFilterTags } from "./components/Filters/components/ColumnFilterTags/columnFilterTags";
|
|
6
7
|
import { Filters } from "./components/Filters/filters";
|
|
@@ -17,7 +18,7 @@ import { useDataDictionaryConfig } from "./hooks/UseDataDictionaryConfig/hook";
|
|
|
17
18
|
import { useMeasureFilters } from "./hooks/UseMeasureFilters/hook";
|
|
18
19
|
export const DataDictionary = ({ className, dictionary, EntitiesLayout = DefaultEntitiesLayout, FiltersLayout = DefaultFiltersLayout, Outline = DefaultOutline, OutlineLayout = DefaultOutlineLayout, Title = DefaultTitle, TitleLayout = DefaultTitleLayout, }) => {
|
|
19
20
|
// Get dictionary configuration.
|
|
20
|
-
const { classes, tableOptions, title } = useDataDictionaryConfig(dictionary);
|
|
21
|
+
const { classes, description, tableOptions, title } = useDataDictionaryConfig(dictionary);
|
|
21
22
|
// Layout measurements.
|
|
22
23
|
// Get header and footer dimensions.
|
|
23
24
|
const { spacing } = useLayoutSpacing();
|
|
@@ -40,5 +41,6 @@ export const DataDictionary = ({ className, dictionary, EntitiesLayout = Default
|
|
|
40
41
|
React.createElement(ColumnFilterTags, { table: table })),
|
|
41
42
|
React.createElement(Fade, { in: dimensions.height > 0 },
|
|
42
43
|
React.createElement(EntitiesLayout, { spacing: entitiesSpacing },
|
|
44
|
+
React.createElement(Description, { description: description }),
|
|
43
45
|
React.createElement(Entities, { spacing: entitiesSpacing, table: table }))))));
|
|
44
46
|
};
|
|
@@ -20,6 +20,7 @@ export const useDataDictionaryConfig = (dictionary) => {
|
|
|
20
20
|
// exists above and would have thrown an error if undefined.
|
|
21
21
|
return {
|
|
22
22
|
classes: dataDictionaryConfig.dataDictionary.classes,
|
|
23
|
+
description: dataDictionaryConfig.dataDictionary.description,
|
|
23
24
|
tableOptions: dataDictionaryConfig.tableOptions,
|
|
24
25
|
title: dataDictionaryConfig.dataDictionary.title,
|
|
25
26
|
};
|
|
@@ -2,6 +2,7 @@ import { RowData, TableOptions } from "@tanstack/react-table";
|
|
|
2
2
|
import { Attribute, Class } from "../../../../common/entities";
|
|
3
3
|
export interface UseDataDictionaryConfig<T extends RowData = Attribute> {
|
|
4
4
|
classes: Class<T>[];
|
|
5
|
+
description?: string;
|
|
5
6
|
tableOptions: Omit<TableOptions<T>, "data" | "getCoreRowModel">;
|
|
6
7
|
title: string;
|
|
7
8
|
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { Row, RowData, Table } from "@tanstack/react-table";
|
|
2
|
-
import {
|
|
2
|
+
import { Virtualizer } from "@tanstack/react-virtual";
|
|
3
3
|
import { ROW_DIRECTION } from "../../common/entities";
|
|
4
4
|
export interface TableBodyProps<T extends RowData> {
|
|
5
5
|
rowDirection: ROW_DIRECTION;
|
|
6
6
|
rows: Row<T>[];
|
|
7
|
-
tableContainerRef: RefObject<HTMLDivElement>;
|
|
8
7
|
tableInstance: Table<T>;
|
|
8
|
+
virtualizer: Virtualizer<HTMLDivElement, Element>;
|
|
9
9
|
}
|
|
10
|
-
export declare const TableBody: <T extends RowData>({ rowDirection, rows,
|
|
10
|
+
export declare const TableBody: <T extends RowData>({ rowDirection, rows, tableInstance, virtualizer, }: TableBodyProps<T>) => JSX.Element;
|
|
@@ -1,22 +1,12 @@
|
|
|
1
1
|
import { TableBody as MTableBody } from "@mui/material";
|
|
2
|
-
import { useVirtualizer } from "@tanstack/react-virtual";
|
|
3
2
|
import React from "react";
|
|
4
3
|
import { ROW_DIRECTION } from "../../common/entities";
|
|
5
4
|
import { CollapsableRows } from "../TableRows/components/CollapsableRows/collapsableRows";
|
|
6
5
|
import { VirtualizedRow } from "../TableRows/components/VirtualizedRow/virtualizedRow";
|
|
7
6
|
import { TableRows } from "../TableRows/tableRows";
|
|
8
|
-
|
|
9
|
-
export const TableBody = ({ rowDirection, rows, tableContainerRef, tableInstance, }) => {
|
|
10
|
-
const virtualizedRows = getAllVirtualizedRows(tableInstance, rows, rowDirection);
|
|
11
|
-
const virtualizer = useVirtualizer({
|
|
12
|
-
count: virtualizedRows.length,
|
|
13
|
-
estimateSize: () => 56,
|
|
14
|
-
gap: 1,
|
|
15
|
-
getScrollElement: () => tableContainerRef.current,
|
|
16
|
-
overscan: 20,
|
|
17
|
-
});
|
|
7
|
+
export const TableBody = ({ rowDirection, rows, tableInstance, virtualizer, }) => {
|
|
18
8
|
return (React.createElement(MTableBody, null,
|
|
19
9
|
React.createElement(VirtualizedRow, { isUpperRow: true, virtualizer: virtualizer }),
|
|
20
|
-
rowDirection === ROW_DIRECTION.DEFAULT ? (React.createElement(TableRows, { rows:
|
|
10
|
+
rowDirection === ROW_DIRECTION.DEFAULT ? (React.createElement(TableRows, { rows: rows, virtualizer: virtualizer })) : (React.createElement(CollapsableRows, { rows: rows, tableInstance: tableInstance, virtualizer: virtualizer })),
|
|
21
11
|
React.createElement(VirtualizedRow, { isUpperRow: false, virtualizer: virtualizer })));
|
|
22
12
|
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { RowData, Table } from "@tanstack/react-table";
|
|
2
|
+
import { ROW_DIRECTION } from "../../common/entities";
|
|
3
|
+
import { UseVirtualizationProps } from "./types";
|
|
4
|
+
export declare const useVirtualization: <T extends RowData>({ rowDirection, table, }: {
|
|
5
|
+
rowDirection: ROW_DIRECTION;
|
|
6
|
+
table: Table<T>;
|
|
7
|
+
}) => UseVirtualizationProps<T>;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { useVirtualizer } from "@tanstack/react-virtual";
|
|
2
|
+
import { useRef } from "react";
|
|
3
|
+
import { getRowsForVirtualization } from "./utils";
|
|
4
|
+
export const useVirtualization = ({ rowDirection, table, }) => {
|
|
5
|
+
// Ref for the scrollable container.
|
|
6
|
+
const scrollElementRef = useRef(null);
|
|
7
|
+
// Derive the list of rows eligible for virtualization based on grouping and row direction.
|
|
8
|
+
const rows = getRowsForVirtualization(table, rowDirection);
|
|
9
|
+
// Build virtualizer instance.
|
|
10
|
+
const virtualizer = useVirtualizer({
|
|
11
|
+
count: rows.length,
|
|
12
|
+
estimateSize: () => 56,
|
|
13
|
+
gap: 1,
|
|
14
|
+
getScrollElement: () => scrollElementRef.current,
|
|
15
|
+
overscan: 20,
|
|
16
|
+
});
|
|
17
|
+
return { rows, scrollElementRef, virtualizer };
|
|
18
|
+
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Row, RowData } from "@tanstack/react-table";
|
|
2
|
+
import { Virtualizer } from "@tanstack/react-virtual";
|
|
3
|
+
import { RefObject } from "react";
|
|
4
|
+
export interface UseVirtualizationProps<T extends RowData> {
|
|
5
|
+
rows: Row<T>[];
|
|
6
|
+
scrollElementRef: RefObject<HTMLDivElement>;
|
|
7
|
+
virtualizer: Virtualizer<HTMLDivElement, Element>;
|
|
8
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -3,10 +3,8 @@ import { ROW_DIRECTION } from "../../common/entities";
|
|
|
3
3
|
/**
|
|
4
4
|
* Filters and returns the appropriate rows for a virtualized table based on row direction
|
|
5
5
|
* and grouping state.
|
|
6
|
-
* Rows are filtered if `ROW_DIRECTION` is `VERTICAL` and the table is grouped.
|
|
7
6
|
* @param table - Table.
|
|
8
|
-
* @param rows - Rows.
|
|
9
7
|
* @param rowDirection - Row direction.
|
|
10
8
|
* @returns Rows based on the provided row direction and table grouping state.
|
|
11
9
|
*/
|
|
12
|
-
export declare function
|
|
10
|
+
export declare function getRowsForVirtualization<T extends RowData>(table: Table<T>, rowDirection: ROW_DIRECTION): Row<T>[];
|
|
@@ -2,16 +2,20 @@ import { ROW_DIRECTION } from "../../common/entities";
|
|
|
2
2
|
/**
|
|
3
3
|
* Filters and returns the appropriate rows for a virtualized table based on row direction
|
|
4
4
|
* and grouping state.
|
|
5
|
-
* Rows are filtered if `ROW_DIRECTION` is `VERTICAL` and the table is grouped.
|
|
6
5
|
* @param table - Table.
|
|
7
|
-
* @param rows - Rows.
|
|
8
6
|
* @param rowDirection - Row direction.
|
|
9
7
|
* @returns Rows based on the provided row direction and table grouping state.
|
|
10
8
|
*/
|
|
11
|
-
export function
|
|
9
|
+
export function getRowsForVirtualization(table, rowDirection) {
|
|
10
|
+
const { getRowModel, getState } = table;
|
|
11
|
+
const { rows } = getRowModel();
|
|
12
|
+
const { grouping } = getState();
|
|
13
|
+
// If the row direction is DEFAULT, return all rows.
|
|
12
14
|
if (rowDirection === ROW_DIRECTION.DEFAULT)
|
|
13
15
|
return rows;
|
|
14
|
-
|
|
16
|
+
// If the table is not grouped, return all rows.
|
|
17
|
+
if (grouping.length === 0)
|
|
15
18
|
return rows;
|
|
19
|
+
// If the row direction is VERTICAL, return only grouped rows.
|
|
16
20
|
return rows.filter(({ getIsGrouped }) => getIsGrouped());
|
|
17
21
|
}
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import { TableContainer } from "@mui/material";
|
|
2
|
-
import React, { Fragment,
|
|
2
|
+
import React, { Fragment, useCallback } from "react";
|
|
3
3
|
import { track } from "../../common/analytics/analytics";
|
|
4
4
|
import { EVENT_NAME, EVENT_PARAM, PAGINATION_DIRECTION, } from "../../common/analytics/entities";
|
|
5
5
|
import { BREAKPOINT_FN_NAME, useBreakpointHelper, } from "../../hooks/useBreakpointHelper";
|
|
6
6
|
import { useExploreMode } from "../../hooks/useExploreMode/useExploreMode";
|
|
7
7
|
import { useExploreState } from "../../hooks/useExploreState";
|
|
8
|
-
import { useScroll } from "../../hooks/useScroll";
|
|
9
8
|
import { ExploreActionKind } from "../../providers/exploreState";
|
|
10
9
|
import { TABLET } from "../../theme/common/breakpoints";
|
|
11
10
|
import { Loading, LOADING_PANEL_STYLE } from "../Loading/loading";
|
|
@@ -17,9 +16,9 @@ import { TableBody } from "./components/TableBody/tableBody";
|
|
|
17
16
|
import { TableHead } from "./components/TableHead/tableHead";
|
|
18
17
|
import { TablePagination } from "./components/TablePagination/tablePagination";
|
|
19
18
|
import { TableToolbar } from "./components/TableToolbar/tableToolbar";
|
|
19
|
+
import { useVirtualization } from "./hooks/UseVirtualization/hook";
|
|
20
20
|
import { GridTable } from "./table.styles";
|
|
21
21
|
export const Table = ({ listView, loading, table, }) => {
|
|
22
|
-
const tableContainerRef = useRef(null);
|
|
23
22
|
const tabletDown = useBreakpointHelper(BREAKPOINT_FN_NAME.DOWN, TABLET);
|
|
24
23
|
const exploreMode = useExploreMode();
|
|
25
24
|
const { exploreDispatch, exploreState } = useExploreState();
|
|
@@ -30,11 +29,13 @@ export const Table = ({ listView, loading, table, }) => {
|
|
|
30
29
|
const rowDirection = tabletDown
|
|
31
30
|
? ROW_DIRECTION.VERTICAL
|
|
32
31
|
: ROW_DIRECTION.DEFAULT;
|
|
33
|
-
const {
|
|
34
|
-
|
|
32
|
+
const { rows, scrollElementRef, virtualizer } = useVirtualization({
|
|
33
|
+
rowDirection,
|
|
34
|
+
table,
|
|
35
|
+
});
|
|
36
|
+
const { getVisibleFlatColumns, nextPage: tableNextPage, previousPage: tablePreviousPage, } = table;
|
|
35
37
|
const noResults = !loading && (!rows || rows.length === 0);
|
|
36
|
-
const
|
|
37
|
-
const handleTableNextPage = () => {
|
|
38
|
+
const handleTableNextPage = useCallback(() => {
|
|
38
39
|
let nextPage = tableNextPage;
|
|
39
40
|
if (!clientFiltering) {
|
|
40
41
|
nextPage = () => {
|
|
@@ -50,9 +51,8 @@ export const Table = ({ listView, loading, table, }) => {
|
|
|
50
51
|
});
|
|
51
52
|
}
|
|
52
53
|
nextPage();
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
const handleTablePreviousPage = () => {
|
|
54
|
+
}, [clientFiltering, exploreDispatch, exploreState, tableNextPage]);
|
|
55
|
+
const handleTablePreviousPage = useCallback(() => {
|
|
56
56
|
let previousPage = tablePreviousPage;
|
|
57
57
|
if (!clientFiltering) {
|
|
58
58
|
previousPage = () => {
|
|
@@ -67,8 +67,7 @@ export const Table = ({ listView, loading, table, }) => {
|
|
|
67
67
|
});
|
|
68
68
|
}
|
|
69
69
|
previousPage();
|
|
70
|
-
|
|
71
|
-
};
|
|
70
|
+
}, [clientFiltering, exploreDispatch, exploreState, tablePreviousPage]);
|
|
72
71
|
function canNextPage() {
|
|
73
72
|
return currentPage < pages;
|
|
74
73
|
}
|
|
@@ -78,9 +77,9 @@ export const Table = ({ listView, loading, table, }) => {
|
|
|
78
77
|
return noResults ? (React.createElement(NoResults, { Paper: null, title: "No Results found" })) : (React.createElement(Fragment, null,
|
|
79
78
|
React.createElement(TableToolbar, { listView: listView, tableInstance: table }),
|
|
80
79
|
React.createElement(Loading, { appear: false, autoPosition: false, loading: loading, panelStyle: LOADING_PANEL_STYLE.INHERIT }),
|
|
81
|
-
React.createElement(TableContainer, { ref:
|
|
80
|
+
React.createElement(TableContainer, { ref: scrollElementRef },
|
|
82
81
|
React.createElement(GridTable, { collapsable: true, gridTemplateColumns: getColumnTrackSizing(getVisibleFlatColumns()), stickyHeader: true },
|
|
83
82
|
React.createElement(TableHead, { tableInstance: table }),
|
|
84
|
-
React.createElement(TableBody, { rows: rows, rowDirection: rowDirection,
|
|
83
|
+
React.createElement(TableBody, { rows: rows, rowDirection: rowDirection, tableInstance: table, virtualizer: virtualizer }))),
|
|
85
84
|
!disablePagination && (React.createElement(TablePagination, { canNextPage: canNextPage(), canPreviousPage: canPreviousPage(), currentPage: currentPage, onNextPage: handleTableNextPage, onPreviousPage: handleTablePreviousPage, totalPage: pages ?? 0 }))));
|
|
86
85
|
};
|
package/package.json
CHANGED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import styled from "@emotion/styled";
|
|
2
|
+
import { PALETTE } from "../../../../styles/common/constants/palette";
|
|
3
|
+
import {
|
|
4
|
+
mediaTabletDown,
|
|
5
|
+
mediaTabletUp,
|
|
6
|
+
} from "../../../../styles/common/mixins/breakpoints";
|
|
7
|
+
import { textHeadingSmall } from "../../../../styles/common/mixins/fonts";
|
|
8
|
+
import { RoundedPaper } from "../../../common/Paper/components/RoundedPaper/roundedPaper";
|
|
9
|
+
import { MarkdownRenderer } from "../../../MarkdownRenderer/markdownRenderer";
|
|
10
|
+
|
|
11
|
+
export const StyledRoundedPaper = styled(RoundedPaper)`
|
|
12
|
+
padding: 20px;
|
|
13
|
+
|
|
14
|
+
${mediaTabletDown} {
|
|
15
|
+
padding: 20px 16px;
|
|
16
|
+
}
|
|
17
|
+
`;
|
|
18
|
+
|
|
19
|
+
export const StyledMarkdownRenderer = styled(MarkdownRenderer)`
|
|
20
|
+
align-self: flex-start;
|
|
21
|
+
|
|
22
|
+
code {
|
|
23
|
+
all: unset;
|
|
24
|
+
font: inherit;
|
|
25
|
+
font-family: Roboto Mono, monospace;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
h2,
|
|
29
|
+
h3,
|
|
30
|
+
h4,
|
|
31
|
+
h5,
|
|
32
|
+
h6 {
|
|
33
|
+
margin: 8px 0;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
h2 {
|
|
37
|
+
${textHeadingSmall};
|
|
38
|
+
font-size: 18px;
|
|
39
|
+
line-height: 26px;
|
|
40
|
+
|
|
41
|
+
${mediaTabletUp} {
|
|
42
|
+
font-size: 18px;
|
|
43
|
+
line-height: 26px;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
hr {
|
|
48
|
+
border: none;
|
|
49
|
+
border-bottom: 1px solid ${PALETTE.SMOKE_MAIN};
|
|
50
|
+
margin: 16px 0;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
p {
|
|
54
|
+
font: inherit;
|
|
55
|
+
}
|
|
56
|
+
`;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import {
|
|
3
|
+
StyledMarkdownRenderer,
|
|
4
|
+
StyledRoundedPaper,
|
|
5
|
+
} from "./description.styles";
|
|
6
|
+
import { DescriptionProps } from "./types";
|
|
7
|
+
|
|
8
|
+
export const Description = ({
|
|
9
|
+
description,
|
|
10
|
+
}: DescriptionProps): JSX.Element | null => {
|
|
11
|
+
if (!description) return null;
|
|
12
|
+
return (
|
|
13
|
+
<StyledRoundedPaper elevation={0}>
|
|
14
|
+
<StyledMarkdownRenderer value={description} />
|
|
15
|
+
</StyledRoundedPaper>
|
|
16
|
+
);
|
|
17
|
+
};
|
|
@@ -7,6 +7,8 @@ const PB = LAYOUT_SPACING.CONTENT_PADDING_BOTTOM; /* bottom padding */
|
|
|
7
7
|
const PT = LAYOUT_SPACING.CONTENT_PADDING_TOP; /* top padding */
|
|
8
8
|
|
|
9
9
|
export const Layout = styled("div")<LayoutSpacing>`
|
|
10
|
+
display: grid;
|
|
11
|
+
gap: 16px;
|
|
10
12
|
grid-column: 2;
|
|
11
13
|
grid-row: 1;
|
|
12
14
|
padding-bottom: ${PB}px;
|
|
@@ -3,6 +3,7 @@ import { RowData } from "@tanstack/react-table";
|
|
|
3
3
|
import React from "react";
|
|
4
4
|
import { Attribute } from "../../common/entities";
|
|
5
5
|
import { useLayoutSpacing } from "../../hooks/UseLayoutSpacing/hook";
|
|
6
|
+
import { Description } from "./components/Description/description";
|
|
6
7
|
import { Entities } from "./components/Entities/entities";
|
|
7
8
|
import { ColumnFilterTags } from "./components/Filters/components/ColumnFilterTags/columnFilterTags";
|
|
8
9
|
import { Filters } from "./components/Filters/filters";
|
|
@@ -30,7 +31,7 @@ export const DataDictionary = <T extends RowData = Attribute>({
|
|
|
30
31
|
TitleLayout = DefaultTitleLayout,
|
|
31
32
|
}: DataDictionaryProps): JSX.Element => {
|
|
32
33
|
// Get dictionary configuration.
|
|
33
|
-
const { classes, tableOptions, title } =
|
|
34
|
+
const { classes, description, tableOptions, title } =
|
|
34
35
|
useDataDictionaryConfig<T>(dictionary);
|
|
35
36
|
|
|
36
37
|
// Layout measurements.
|
|
@@ -64,6 +65,7 @@ export const DataDictionary = <T extends RowData = Attribute>({
|
|
|
64
65
|
<Fade in={dimensions.height > 0}>
|
|
65
66
|
{/* Fade in entities when filters are measured. */}
|
|
66
67
|
<EntitiesLayout spacing={entitiesSpacing}>
|
|
68
|
+
<Description description={description} />
|
|
67
69
|
<Entities spacing={entitiesSpacing} table={table} />
|
|
68
70
|
</EntitiesLayout>
|
|
69
71
|
</Fade>
|
|
@@ -31,6 +31,7 @@ export const useDataDictionaryConfig = <T extends RowData = Attribute>(
|
|
|
31
31
|
// exists above and would have thrown an error if undefined.
|
|
32
32
|
return {
|
|
33
33
|
classes: dataDictionaryConfig!.dataDictionary.classes,
|
|
34
|
+
description: dataDictionaryConfig!.dataDictionary.description,
|
|
34
35
|
tableOptions: dataDictionaryConfig!.tableOptions,
|
|
35
36
|
title: dataDictionaryConfig!.dataDictionary.title,
|
|
36
37
|
};
|
|
@@ -3,6 +3,7 @@ import { Attribute, Class } from "../../../../common/entities";
|
|
|
3
3
|
|
|
4
4
|
export interface UseDataDictionaryConfig<T extends RowData = Attribute> {
|
|
5
5
|
classes: Class<T>[];
|
|
6
|
+
description?: string;
|
|
6
7
|
tableOptions: Omit<TableOptions<T>, "data" | "getCoreRowModel">;
|
|
7
8
|
title: string;
|
|
8
9
|
}
|
|
@@ -1,46 +1,33 @@
|
|
|
1
1
|
import { TableBody as MTableBody } from "@mui/material";
|
|
2
2
|
import { Row, RowData, Table } from "@tanstack/react-table";
|
|
3
|
-
import {
|
|
4
|
-
import React
|
|
3
|
+
import { Virtualizer } from "@tanstack/react-virtual";
|
|
4
|
+
import React from "react";
|
|
5
5
|
import { ROW_DIRECTION } from "../../common/entities";
|
|
6
6
|
import { CollapsableRows } from "../TableRows/components/CollapsableRows/collapsableRows";
|
|
7
7
|
import { VirtualizedRow } from "../TableRows/components/VirtualizedRow/virtualizedRow";
|
|
8
8
|
import { TableRows } from "../TableRows/tableRows";
|
|
9
|
-
import { getAllVirtualizedRows } from "./utils";
|
|
10
9
|
|
|
11
10
|
export interface TableBodyProps<T extends RowData> {
|
|
12
11
|
rowDirection: ROW_DIRECTION;
|
|
13
12
|
rows: Row<T>[];
|
|
14
|
-
tableContainerRef: RefObject<HTMLDivElement>;
|
|
15
13
|
tableInstance: Table<T>;
|
|
14
|
+
virtualizer: Virtualizer<HTMLDivElement, Element>;
|
|
16
15
|
}
|
|
17
16
|
|
|
18
17
|
export const TableBody = <T extends RowData>({
|
|
19
18
|
rowDirection,
|
|
20
19
|
rows,
|
|
21
|
-
tableContainerRef,
|
|
22
20
|
tableInstance,
|
|
21
|
+
virtualizer,
|
|
23
22
|
}: TableBodyProps<T>): JSX.Element => {
|
|
24
|
-
const virtualizedRows = getAllVirtualizedRows(
|
|
25
|
-
tableInstance,
|
|
26
|
-
rows,
|
|
27
|
-
rowDirection
|
|
28
|
-
);
|
|
29
|
-
const virtualizer = useVirtualizer({
|
|
30
|
-
count: virtualizedRows.length,
|
|
31
|
-
estimateSize: () => 56,
|
|
32
|
-
gap: 1,
|
|
33
|
-
getScrollElement: () => tableContainerRef.current,
|
|
34
|
-
overscan: 20,
|
|
35
|
-
});
|
|
36
23
|
return (
|
|
37
24
|
<MTableBody>
|
|
38
25
|
<VirtualizedRow isUpperRow={true} virtualizer={virtualizer} />
|
|
39
26
|
{rowDirection === ROW_DIRECTION.DEFAULT ? (
|
|
40
|
-
<TableRows rows={
|
|
27
|
+
<TableRows rows={rows} virtualizer={virtualizer} />
|
|
41
28
|
) : (
|
|
42
29
|
<CollapsableRows
|
|
43
|
-
rows={
|
|
30
|
+
rows={rows}
|
|
44
31
|
tableInstance={tableInstance}
|
|
45
32
|
virtualizer={virtualizer}
|
|
46
33
|
/>
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { RowData, Table } from "@tanstack/react-table";
|
|
2
|
+
import { useVirtualizer } from "@tanstack/react-virtual";
|
|
3
|
+
import { useRef } from "react";
|
|
4
|
+
import { ROW_DIRECTION } from "../../common/entities";
|
|
5
|
+
import { UseVirtualizationProps } from "./types";
|
|
6
|
+
import { getRowsForVirtualization } from "./utils";
|
|
7
|
+
|
|
8
|
+
export const useVirtualization = <T extends RowData>({
|
|
9
|
+
rowDirection,
|
|
10
|
+
table,
|
|
11
|
+
}: {
|
|
12
|
+
rowDirection: ROW_DIRECTION;
|
|
13
|
+
table: Table<T>;
|
|
14
|
+
}): UseVirtualizationProps<T> => {
|
|
15
|
+
// Ref for the scrollable container.
|
|
16
|
+
const scrollElementRef = useRef<HTMLDivElement>(null);
|
|
17
|
+
|
|
18
|
+
// Derive the list of rows eligible for virtualization based on grouping and row direction.
|
|
19
|
+
const rows = getRowsForVirtualization(table, rowDirection);
|
|
20
|
+
|
|
21
|
+
// Build virtualizer instance.
|
|
22
|
+
const virtualizer = useVirtualizer({
|
|
23
|
+
count: rows.length,
|
|
24
|
+
estimateSize: () => 56,
|
|
25
|
+
gap: 1,
|
|
26
|
+
getScrollElement: () => scrollElementRef.current,
|
|
27
|
+
overscan: 20,
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
return { rows, scrollElementRef, virtualizer };
|
|
31
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Row, RowData } from "@tanstack/react-table";
|
|
2
|
+
import { Virtualizer } from "@tanstack/react-virtual";
|
|
3
|
+
import { RefObject } from "react";
|
|
4
|
+
|
|
5
|
+
export interface UseVirtualizationProps<T extends RowData> {
|
|
6
|
+
rows: Row<T>[];
|
|
7
|
+
scrollElementRef: RefObject<HTMLDivElement>;
|
|
8
|
+
virtualizer: Virtualizer<HTMLDivElement, Element>;
|
|
9
|
+
}
|
|
@@ -4,18 +4,24 @@ import { ROW_DIRECTION } from "../../common/entities";
|
|
|
4
4
|
/**
|
|
5
5
|
* Filters and returns the appropriate rows for a virtualized table based on row direction
|
|
6
6
|
* and grouping state.
|
|
7
|
-
* Rows are filtered if `ROW_DIRECTION` is `VERTICAL` and the table is grouped.
|
|
8
7
|
* @param table - Table.
|
|
9
|
-
* @param rows - Rows.
|
|
10
8
|
* @param rowDirection - Row direction.
|
|
11
9
|
* @returns Rows based on the provided row direction and table grouping state.
|
|
12
10
|
*/
|
|
13
|
-
export function
|
|
11
|
+
export function getRowsForVirtualization<T extends RowData>(
|
|
14
12
|
table: Table<T>,
|
|
15
|
-
rows: Row<T>[],
|
|
16
13
|
rowDirection: ROW_DIRECTION
|
|
17
14
|
): Row<T>[] {
|
|
15
|
+
const { getRowModel, getState } = table;
|
|
16
|
+
const { rows } = getRowModel();
|
|
17
|
+
const { grouping } = getState();
|
|
18
|
+
|
|
19
|
+
// If the row direction is DEFAULT, return all rows.
|
|
18
20
|
if (rowDirection === ROW_DIRECTION.DEFAULT) return rows;
|
|
19
|
-
|
|
21
|
+
|
|
22
|
+
// If the table is not grouped, return all rows.
|
|
23
|
+
if (grouping.length === 0) return rows;
|
|
24
|
+
|
|
25
|
+
// If the row direction is VERTICAL, return only grouped rows.
|
|
20
26
|
return rows.filter(({ getIsGrouped }) => getIsGrouped());
|
|
21
27
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { TableContainer } from "@mui/material";
|
|
2
2
|
import { RowData, Table as TanStackTable } from "@tanstack/react-table";
|
|
3
|
-
import React, { Fragment,
|
|
3
|
+
import React, { Fragment, useCallback } from "react";
|
|
4
4
|
import { track } from "../../common/analytics/analytics";
|
|
5
5
|
import {
|
|
6
6
|
EVENT_NAME,
|
|
@@ -14,7 +14,6 @@ import {
|
|
|
14
14
|
} from "../../hooks/useBreakpointHelper";
|
|
15
15
|
import { useExploreMode } from "../../hooks/useExploreMode/useExploreMode";
|
|
16
16
|
import { useExploreState } from "../../hooks/useExploreState";
|
|
17
|
-
import { useScroll } from "../../hooks/useScroll";
|
|
18
17
|
import { ExploreActionKind } from "../../providers/exploreState";
|
|
19
18
|
import { TABLET } from "../../theme/common/breakpoints";
|
|
20
19
|
import { Loading, LOADING_PANEL_STYLE } from "../Loading/loading";
|
|
@@ -26,6 +25,7 @@ import { TableBody } from "./components/TableBody/tableBody";
|
|
|
26
25
|
import { TableHead } from "./components/TableHead/tableHead";
|
|
27
26
|
import { TablePagination } from "./components/TablePagination/tablePagination";
|
|
28
27
|
import { TableToolbar } from "./components/TableToolbar/tableToolbar";
|
|
28
|
+
import { useVirtualization } from "./hooks/UseVirtualization/hook";
|
|
29
29
|
import { GridTable } from "./table.styles";
|
|
30
30
|
|
|
31
31
|
export interface TableProps<T extends RowData> {
|
|
@@ -39,7 +39,6 @@ export const Table = <T extends RowData>({
|
|
|
39
39
|
loading,
|
|
40
40
|
table,
|
|
41
41
|
}: TableProps<T>): JSX.Element => {
|
|
42
|
-
const tableContainerRef = useRef<HTMLDivElement>(null);
|
|
43
42
|
const tabletDown = useBreakpointHelper(BREAKPOINT_FN_NAME.DOWN, TABLET);
|
|
44
43
|
const exploreMode = useExploreMode();
|
|
45
44
|
const { exploreDispatch, exploreState } = useExploreState();
|
|
@@ -50,19 +49,20 @@ export const Table = <T extends RowData>({
|
|
|
50
49
|
const rowDirection = tabletDown
|
|
51
50
|
? ROW_DIRECTION.VERTICAL
|
|
52
51
|
: ROW_DIRECTION.DEFAULT;
|
|
52
|
+
const { rows, scrollElementRef, virtualizer } = useVirtualization({
|
|
53
|
+
rowDirection,
|
|
54
|
+
table,
|
|
55
|
+
});
|
|
53
56
|
|
|
54
57
|
const {
|
|
55
|
-
getRowModel,
|
|
56
58
|
getVisibleFlatColumns,
|
|
57
59
|
nextPage: tableNextPage,
|
|
58
60
|
previousPage: tablePreviousPage,
|
|
59
61
|
} = table;
|
|
60
62
|
|
|
61
|
-
const { rows } = getRowModel();
|
|
62
63
|
const noResults = !loading && (!rows || rows.length === 0);
|
|
63
|
-
const scrollTop = useScroll();
|
|
64
64
|
|
|
65
|
-
const handleTableNextPage = (): void => {
|
|
65
|
+
const handleTableNextPage = useCallback((): void => {
|
|
66
66
|
let nextPage = tableNextPage;
|
|
67
67
|
if (!clientFiltering) {
|
|
68
68
|
nextPage = (): void => {
|
|
@@ -78,10 +78,9 @@ export const Table = <T extends RowData>({
|
|
|
78
78
|
});
|
|
79
79
|
}
|
|
80
80
|
nextPage();
|
|
81
|
-
|
|
82
|
-
};
|
|
81
|
+
}, [clientFiltering, exploreDispatch, exploreState, tableNextPage]);
|
|
83
82
|
|
|
84
|
-
const handleTablePreviousPage = (): void => {
|
|
83
|
+
const handleTablePreviousPage = useCallback((): void => {
|
|
85
84
|
let previousPage = tablePreviousPage;
|
|
86
85
|
if (!clientFiltering) {
|
|
87
86
|
previousPage = (): void => {
|
|
@@ -96,8 +95,7 @@ export const Table = <T extends RowData>({
|
|
|
96
95
|
});
|
|
97
96
|
}
|
|
98
97
|
previousPage();
|
|
99
|
-
|
|
100
|
-
};
|
|
98
|
+
}, [clientFiltering, exploreDispatch, exploreState, tablePreviousPage]);
|
|
101
99
|
|
|
102
100
|
function canNextPage(): boolean {
|
|
103
101
|
return currentPage < pages;
|
|
@@ -118,7 +116,7 @@ export const Table = <T extends RowData>({
|
|
|
118
116
|
loading={loading}
|
|
119
117
|
panelStyle={LOADING_PANEL_STYLE.INHERIT}
|
|
120
118
|
/>
|
|
121
|
-
<TableContainer ref={
|
|
119
|
+
<TableContainer ref={scrollElementRef}>
|
|
122
120
|
<GridTable
|
|
123
121
|
collapsable={true}
|
|
124
122
|
gridTemplateColumns={getColumnTrackSizing(getVisibleFlatColumns())}
|
|
@@ -128,8 +126,8 @@ export const Table = <T extends RowData>({
|
|
|
128
126
|
<TableBody
|
|
129
127
|
rows={rows}
|
|
130
128
|
rowDirection={rowDirection}
|
|
131
|
-
tableContainerRef={tableContainerRef}
|
|
132
129
|
tableInstance={table}
|
|
130
|
+
virtualizer={virtualizer}
|
|
133
131
|
/>
|
|
134
132
|
</GridTable>
|
|
135
133
|
</TableContainer>
|
package/lib/hooks/useScroll.d.ts
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
type ScrollType = "top" | "bottom";
|
|
2
|
-
type UseScrollReturn = () => void;
|
|
3
|
-
/**
|
|
4
|
-
* Hook used to scroll the to top or bottom of the page.
|
|
5
|
-
* This hook can only be used on the client-side.
|
|
6
|
-
* @param scrollType - top or bottom of the page. Default = top
|
|
7
|
-
* @returns scroll function
|
|
8
|
-
*/
|
|
9
|
-
export declare const useScroll: (scrollType?: ScrollType) => UseScrollReturn;
|
|
10
|
-
export {};
|
package/lib/hooks/useScroll.js
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { useCallback } from "react";
|
|
2
|
-
/**
|
|
3
|
-
* Hook used to scroll the to top or bottom of the page.
|
|
4
|
-
* This hook can only be used on the client-side.
|
|
5
|
-
* @param scrollType - top or bottom of the page. Default = top
|
|
6
|
-
* @returns scroll function
|
|
7
|
-
*/
|
|
8
|
-
export const useScroll = (scrollType = "top") => {
|
|
9
|
-
return useCallback(() => window.scrollTo({
|
|
10
|
-
top: scrollType === "top" ? 0 : document.body.scrollHeight,
|
|
11
|
-
}), [scrollType]);
|
|
12
|
-
};
|
package/src/hooks/useScroll.ts
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import { useCallback } from "react";
|
|
2
|
-
|
|
3
|
-
type ScrollType = "top" | "bottom";
|
|
4
|
-
|
|
5
|
-
type UseScrollReturn = () => void;
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Hook used to scroll the to top or bottom of the page.
|
|
9
|
-
* This hook can only be used on the client-side.
|
|
10
|
-
* @param scrollType - top or bottom of the page. Default = top
|
|
11
|
-
* @returns scroll function
|
|
12
|
-
*/
|
|
13
|
-
export const useScroll = (scrollType: ScrollType = "top"): UseScrollReturn => {
|
|
14
|
-
return useCallback(
|
|
15
|
-
() =>
|
|
16
|
-
window.scrollTo({
|
|
17
|
-
top: scrollType === "top" ? 0 : document.body.scrollHeight,
|
|
18
|
-
}),
|
|
19
|
-
[scrollType]
|
|
20
|
-
);
|
|
21
|
-
};
|