Files
rowy/src/components/Table/ColumnHeader/ColumnHeaderSort.tsx

121 lines
3.4 KiB
TypeScript
Raw Normal View History

import { memo } from "react";
import { useSetAtom } from "jotai";
2022-06-02 12:44:28 +10:00
import { colord } from "colord";
2022-05-24 16:17:09 +10:00
import { Tooltip, IconButton } from "@mui/material";
import SortDescIcon from "@mui/icons-material/ArrowDownward";
2022-05-30 13:26:57 +10:00
import IconSlash, {
ICON_SLASH_STROKE_DASHOFFSET,
} from "@src/components/IconSlash";
2022-05-24 16:17:09 +10:00
import { tableScope, tableSortsAtom } from "@src/atoms/tableScope";
2023-02-01 13:39:50 +00:00
import useSaveTableSorts from "./useSaveTableSorts";
2022-05-24 16:17:09 +10:00
export const SORT_STATES = ["none", "desc", "asc"] as const;
2022-05-24 16:17:09 +10:00
export interface IColumnHeaderSortProps {
sortKey: string;
currentSort: typeof SORT_STATES[number];
tabIndex?: number;
2023-02-01 07:37:20 +00:00
canEditColumns: boolean;
2022-05-24 16:17:09 +10:00
}
2022-11-18 17:31:03 +11:00
/**
* Renders button with current sort state.
* On click, updates `tableSortsAtom` in `tableScope`.
*/
export const ColumnHeaderSort = memo(function ColumnHeaderSort({
sortKey,
currentSort,
tabIndex,
2023-02-01 07:37:20 +00:00
canEditColumns,
}: IColumnHeaderSortProps) {
const setTableSorts = useSetAtom(tableSortsAtom, tableScope);
2022-05-24 16:17:09 +10:00
const nextSort =
SORT_STATES[SORT_STATES.indexOf(currentSort) + 1] ?? SORT_STATES[0];
2023-02-01 13:39:50 +00:00
const triggerSaveTableSorts = useSaveTableSorts(canEditColumns);
2023-02-01 07:37:20 +00:00
2022-05-24 16:17:09 +10:00
const handleSortClick = () => {
2023-06-01 10:38:08 +05:30
setTableSorts(
nextSort === "none" ? [] : [{ key: sortKey, direction: nextSort }]
);
triggerSaveTableSorts(
nextSort === "none" ? [] : [{ key: sortKey, direction: nextSort }]
);
2022-05-24 16:17:09 +10:00
};
return (
<Tooltip
title={nextSort === "none" ? "Remove sort" : `Sort by ${nextSort}ending`}
2022-05-24 16:17:09 +10:00
>
<IconButton
disableFocusRipple={true}
size="small"
onClick={handleSortClick}
color="inherit"
tabIndex={tabIndex}
2022-05-24 16:17:09 +10:00
sx={{
bgcolor: "background.default",
"&:hover, &:focus": {
backgroundColor: (theme) =>
colord(theme.palette.background.default)
.mix(
theme.palette.action.hover,
theme.palette.action.hoverOpacity
)
.alpha(1)
.toHslString(),
2022-05-26 19:59:59 +10:00
2022-05-30 13:26:57 +10:00
"& .icon-slash-mask": {
2022-05-26 19:59:59 +10:00
stroke: (theme) =>
colord(theme.palette.background.default)
.mix(
theme.palette.action.hover,
theme.palette.action.hoverOpacity
)
.alpha(1)
.toHslString(),
},
},
2022-05-24 16:17:09 +10:00
position: "relative",
opacity: currentSort !== "none" ? 1 : 0,
2022-05-26 19:59:59 +10:00
"& .arrow": {
transition: (theme) =>
theme.transitions.create("transform", {
2022-05-24 16:17:09 +10:00
duration: theme.transitions.duration.short,
2022-05-26 19:59:59 +10:00
}),
2022-05-24 16:17:09 +10:00
2022-05-26 19:59:59 +10:00
transform: currentSort === "asc" ? "rotate(180deg)" : "none",
},
"&:hover .arrow, &:focus .arrow": {
2022-05-24 16:17:09 +10:00
transform:
currentSort === "asc" || nextSort === "asc"
? "rotate(180deg)"
: "none",
},
2022-05-30 13:26:57 +10:00
"& .icon-slash": {
strokeDashoffset:
currentSort === "none" ? 0 : ICON_SLASH_STROKE_DASHOFFSET,
2022-05-26 19:59:59 +10:00
},
"&:hover .icon-slash, &:focus .icon-slash": {
2022-05-30 13:26:57 +10:00
strokeDashoffset:
nextSort === "none" ? 0 : ICON_SLASH_STROKE_DASHOFFSET,
2022-05-26 19:59:59 +10:00
},
2022-05-24 16:17:09 +10:00
}}
>
2022-05-30 14:06:19 +10:00
<div style={{ position: "relative" }}>
<SortDescIcon className="arrow" />
<IconSlash />
</div>
2022-05-24 16:17:09 +10:00
</IconButton>
</Tooltip>
);
});
export default ColumnHeaderSort;