This PR moves the entire project to Typescript. Due to the ~1000 ignores this will lead to a messy codebase for a while, but the churn is worth it – all of those ignore comments are places that were never type-safe previously. closes #1282
71 lines
1.4 KiB
TypeScript
71 lines
1.4 KiB
TypeScript
import { StarredIcon, UnstarredIcon } from "outline-icons";
|
|
import * as React from "react";
|
|
import { useTranslation } from "react-i18next";
|
|
import styled from "styled-components";
|
|
import Document from "~/models/Document";
|
|
import NudeButton from "./NudeButton";
|
|
|
|
type Props = {
|
|
document: Document;
|
|
size?: number;
|
|
};
|
|
|
|
function Star({ size, document, ...rest }: Props) {
|
|
const { t } = useTranslation();
|
|
|
|
const handleClick = React.useCallback(
|
|
(ev: React.MouseEvent<HTMLButtonElement>) => {
|
|
ev.preventDefault();
|
|
ev.stopPropagation();
|
|
|
|
if (document.isStarred) {
|
|
document.unstar();
|
|
} else {
|
|
document.star();
|
|
}
|
|
},
|
|
[document]
|
|
);
|
|
|
|
if (!document) {
|
|
return null;
|
|
}
|
|
|
|
return (
|
|
<Button
|
|
onClick={handleClick}
|
|
size={size}
|
|
aria-label={document.isStarred ? t("Unstar") : t("Star")}
|
|
{...rest}
|
|
>
|
|
{document.isStarred ? (
|
|
<AnimatedStar size={size} color="currentColor" />
|
|
) : (
|
|
<AnimatedStar size={size} color="currentColor" as={UnstarredIcon} />
|
|
)}
|
|
</Button>
|
|
);
|
|
}
|
|
|
|
const Button = styled(NudeButton)`
|
|
color: ${(props) => props.theme.text};
|
|
`;
|
|
|
|
export const AnimatedStar = styled(StarredIcon)`
|
|
flex-shrink: 0;
|
|
transition: all 100ms ease-in-out;
|
|
|
|
&:hover {
|
|
transform: scale(1.1);
|
|
}
|
|
&:active {
|
|
transform: scale(0.95);
|
|
}
|
|
|
|
@media print {
|
|
display: none;
|
|
}
|
|
`;
|
|
|
|
export default Star;
|