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

118 lines
3.5 KiB
TypeScript
Raw Normal View History

2022-05-24 16:17:09 +10:00
import { useAtom } from "jotai";
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, tableOrdersAtom } from "@src/atoms/tableScope";
import { FieldType } from "@src/constants/fields";
import { getFieldProp } from "@src/components/fields";
import { ColumnConfig } from "@src/types/table";
import { colord, extend } from "colord";
import mixPlugin from "colord/plugins/lch";
extend([mixPlugin]);
2022-05-24 16:17:09 +10:00
const SORT_STATES = ["none", "desc", "asc"] as const;
export interface IColumnHeaderSortProps {
column: ColumnConfig;
}
export default function ColumnHeaderSort({ column }: IColumnHeaderSortProps) {
const [tableOrders, setTableOrders] = useAtom(tableOrdersAtom, tableScope);
const _sortKey = getFieldProp("sortKey", (column as any).type);
const sortKey = _sortKey ? `${column.key}.${_sortKey}` : column.key;
const currentSort: typeof SORT_STATES[number] =
tableOrders[0]?.key !== sortKey
? "none"
: tableOrders[0]?.direction || "none";
const nextSort =
SORT_STATES[SORT_STATES.indexOf(currentSort) + 1] ?? SORT_STATES[0];
const handleSortClick = () => {
if (nextSort === "none") setTableOrders([]);
else setTableOrders([{ key: sortKey, direction: nextSort }]);
};
if (column.type === FieldType.id) return null;
return (
<Tooltip
title={nextSort === "none" ? "Unsort" : `Sort by ${nextSort}ending`}
>
<IconButton
disableFocusRipple={true}
size="small"
onClick={handleSortClick}
color="inherit"
sx={{
bgcolor: "background.default",
"&:hover": {
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,
".column-header:hover &": { opacity: 1 },
transition: (theme) =>
2022-05-26 19:59:59 +10:00
theme.transitions.create(["background-color", "opacity"], {
duration: theme.transitions.duration.short,
}),
"& .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": {
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-05-30 13:26:57 +10:00
"&:hover .icon-slash": {
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-26 19:59:59 +10:00
<SortDescIcon className="arrow" />
2022-05-30 13:26:57 +10:00
<IconSlash />
2022-05-24 16:17:09 +10:00
</IconButton>
</Tooltip>
);
}