diff --git a/browser/src/MitochondrialVariantPage/MitochondrialVariantPopulationFrequenciesTable.tsx b/browser/src/MitochondrialVariantPage/MitochondrialVariantPopulationFrequenciesTable.tsx index 6fd259dac..d7ccbb98e 100644 --- a/browser/src/MitochondrialVariantPage/MitochondrialVariantPopulationFrequenciesTable.tsx +++ b/browser/src/MitochondrialVariantPage/MitochondrialVariantPopulationFrequenciesTable.tsx @@ -1,12 +1,14 @@ -import React, { ReactNode, useCallback, useState } from 'react' +import React from 'react' import styled from 'styled-components' -import { BaseTable, TooltipAnchor, TooltipHint } from '@gnomad/ui' +import { BaseTable } from '@gnomad/ui' import { GNOMAD_POPULATION_NAMES } from '@gnomad/dataset-metadata/gnomadPopulations' import { MitochondrialVariant, MitochondrialVariantPopulation } from './MitochondrialVariantPage' +import useTableSort, { ColumnSpecifier, numericCompareFunction } from '../useTableSort' + const CountCell = styled.span` display: inline-block; width: 7ch; @@ -31,98 +33,6 @@ const Table = styled(BaseTable)` } ` -type RowCompareFunction = (a: RowData, b: RowData) => number - -type ColumnSpecifier = { - key: keyof RowData - label: string - tooltip: string | null - compareValueFunction: RowCompareFunction -} - -const renderColumnHeader = ( - key: keyof RowData, - sortBy: keyof RowData, - setSortBy: (key: keyof RowData) => void, - sortAscending: boolean, - label: string, - tooltip: string | null, - compareValueFunction: RowCompareFunction -) => { - let ariaSortAttr: React.AriaAttributes['aria-sort'] = 'none' - if (sortBy === key) { - ariaSortAttr = sortAscending ? 'ascending' : 'descending' - } - - return tooltip ? ( - - {/* @ts-expect-error TS(2322) FIXME: Type '{ children: Element; tooltip: any; }' is not... Remove this comment to see the full error message */} - - - - - ) : ( - - - - ) -} - -// .sort((a, b) => { -// const [population1, population2] = sortAscending ? [a, b] : [b, a] -// -// return sortBy === 'id' -// ? GNOMAD_POPULATION_NAMES[population1.id].localeCompare( -// GNOMAD_POPULATION_NAMES[population2.id] -// ) -// : population1[sortBy] - population2[sortBy] -// }) */ - -const useSort = ( - columnSpecifiers: ColumnSpecifier[], - defaultSortKey: keyof RowData, - rowData: RowData[] -): { headers: ReactNode; sortedRowData: RowData[] } => { - const [key, setKey] = useState(defaultSortKey) - const [ascending, setAscending] = useState(false) - - const setSortKey = useCallback( - (newKey: keyof RowData) => { - setKey(newKey) - setAscending(newKey === key ? !ascending : false) - }, - [key, ascending] - ) - - const { compareValueFunction } = columnSpecifiers.find((column) => column.key === key)! - const sortedRowData = [...rowData].sort((a, b) => { - const ascendingCompare = compareValueFunction(a, b) - return ascending ? ascendingCompare : -ascendingCompare - }) - - const headers = ( - <> - {columnSpecifiers.map((columnSpecifier) => - renderColumnHeader( - columnSpecifier.key, - key, - setSortKey, - ascending, - columnSpecifier.label, - columnSpecifier.tooltip, - columnSpecifier.compareValueFunction - ) - )} - - ) - return { headers, sortedRowData } -} - type MitochondrialVariantPopulationFrequenciesTableProps = { variant: MitochondrialVariant } @@ -132,15 +42,6 @@ type MitochondrialVariantPopulationWithFrequency = MitochondrialVariantPopulatio af_het: number } -type NumberHolder = { - [K in Key]: number -} - -export const numericCompareFunction = - (key: Key) => - >(a: RowData, b: RowData) => - a[key] - b[key] - const comparePopulationNames = ( a: MitochondrialVariantPopulationWithFrequency, b: MitochondrialVariantPopulationWithFrequency @@ -199,7 +100,7 @@ const MitochondrialVariantPopulationFrequenciesTable = ({ af_het: population.an !== 0 ? population.ac_het / population.an : 0, })) - const { headers, sortedRowData } = useSort( + const { headers, sortedRowData } = useTableSort( columnSpecifiers, 'af_hom', populationsWithFrequencies diff --git a/browser/src/useTableSort.tsx b/browser/src/useTableSort.tsx new file mode 100644 index 000000000..1a53c5526 --- /dev/null +++ b/browser/src/useTableSort.tsx @@ -0,0 +1,93 @@ +import React, { useCallback, useState, ReactNode } from 'react' +import { TooltipAnchor, TooltipHint } from '@gnomad/ui' + +export type RowCompareFunction = (a: RowData, b: RowData) => number + +export type ColumnSpecifier = { + key: keyof RowData + label: string + tooltip: string | null + compareValueFunction: RowCompareFunction +} + +const renderColumnHeader = ( + key: keyof RowData, + sortBy: keyof RowData, + setSortBy: (key: keyof RowData) => void, + sortAscending: boolean, + label: string, + tooltip: string | null +) => { + let ariaSortAttr: React.AriaAttributes['aria-sort'] = 'none' + if (sortBy === key) { + ariaSortAttr = sortAscending ? 'ascending' : 'descending' + } + + return tooltip ? ( + + {/* @ts-expect-error TS(2322) FIXME: Type '{ children: Element; tooltip: any; }' is not... Remove this comment to see the full error message */} + + + + + ) : ( + + + + ) +} + +const useTableSort = ( + columnSpecifiers: ColumnSpecifier[], + defaultSortKey: keyof RowData, + rowData: RowData[] +): { headers: ReactNode; sortedRowData: RowData[] } => { + const [key, setKey] = useState(defaultSortKey) + const [ascending, setAscending] = useState(false) + + const setSortKey = useCallback( + (newKey: keyof RowData) => { + setKey(newKey) + setAscending(newKey === key ? !ascending : false) + }, + [key, ascending] + ) + + const { compareValueFunction } = columnSpecifiers.find((column) => column.key === key)! + const sortedRowData = [...rowData].sort((a, b) => { + const ascendingCompare = compareValueFunction(a, b) + return ascending ? ascendingCompare : -ascendingCompare + }) + + const headers = ( + <> + {columnSpecifiers.map((columnSpecifier) => + renderColumnHeader( + columnSpecifier.key, + key, + setSortKey, + ascending, + columnSpecifier.label, + columnSpecifier.tooltip + ) + )} + + ) + return { headers, sortedRowData } +} + +type NumberHolder = { + [K in Key]: number +} + +export const numericCompareFunction = + (key: Key) => + >(a: RowData, b: RowData) => + a[key] - b[key] + +export default useTableSort