2022-11-17 18:17:43 +11:00
|
|
|
import { memo } from "react";
|
2022-10-31 17:04:18 +11:00
|
|
|
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
|
|
|
|
2022-06-13 23:10:15 +10:00
|
|
|
import { tableScope, tableSortsAtom } from "@src/atoms/tableScope";
|
2023-02-01 07:37:20 +00:00
|
|
|
import useSaveTableSortBy from "./useSaveTableSorts";
|
2022-05-24 16:17:09 +10:00
|
|
|
|
2022-10-31 17:04:18 +11:00
|
|
|
export const SORT_STATES = ["none", "desc", "asc"] as const;
|
2022-05-24 16:17:09 +10:00
|
|
|
|
|
|
|
|
export interface IColumnHeaderSortProps {
|
2022-10-31 17:04:18 +11:00
|
|
|
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`.
|
|
|
|
|
*/
|
2022-11-17 18:17:43 +11:00
|
|
|
export const ColumnHeaderSort = memo(function ColumnHeaderSort({
|
2022-10-31 17:04:18 +11:00
|
|
|
sortKey,
|
|
|
|
|
currentSort,
|
|
|
|
|
tabIndex,
|
2023-02-01 07:37:20 +00:00
|
|
|
canEditColumns,
|
2022-10-31 17:04:18 +11:00
|
|
|
}: 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 07:37:20 +00:00
|
|
|
const trigger = useSaveTableSortBy(canEditColumns);
|
|
|
|
|
|
2022-05-24 16:17:09 +10:00
|
|
|
const handleSortClick = () => {
|
2022-06-13 23:10:15 +10:00
|
|
|
if (nextSort === "none") setTableSorts([]);
|
|
|
|
|
else setTableSorts([{ key: sortKey, direction: nextSort }]);
|
2023-02-01 07:37:20 +00:00
|
|
|
trigger([
|
|
|
|
|
{ key: sortKey, direction: nextSort === "none" ? "asc" : nextSort },
|
|
|
|
|
]);
|
2022-05-24 16:17:09 +10:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<Tooltip
|
2022-11-17 18:17:43 +11:00
|
|
|
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"
|
2022-10-31 17:04:18 +11:00
|
|
|
tabIndex={tabIndex}
|
2022-05-24 16:17:09 +10:00
|
|
|
sx={{
|
2022-05-26 19:31:56 +10:00
|
|
|
bgcolor: "background.default",
|
2022-10-31 17:04:18 +11:00
|
|
|
"&:hover, &:focus": {
|
2022-05-26 19:31:56 +10:00
|
|
|
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-26 19:31:56 +10:00
|
|
|
},
|
|
|
|
|
|
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",
|
|
|
|
|
},
|
2022-10-31 17:04:18 +11:00
|
|
|
"&: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
|
|
|
},
|
2022-10-31 17:04:18 +11: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>
|
|
|
|
|
);
|
2022-11-17 18:17:43 +11:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
export default ColumnHeaderSort;
|