noogle/components/preview/preview.tsx

265 lines
8.1 KiB
TypeScript
Raw Normal View History

2022-12-12 16:24:16 +03:00
import React, { useEffect } from "react";
2022-11-26 12:36:08 +03:00
import {
Box,
2022-12-09 18:41:59 +03:00
Container,
IconButton,
2022-11-26 12:36:08 +03:00
List,
ListItem,
ListItemIcon,
ListItemText,
Tooltip,
2022-11-26 12:36:08 +03:00
Typography,
2022-12-12 16:24:16 +03:00
useTheme,
Link as MuiLink,
2022-11-26 12:36:08 +03:00
} from "@mui/material";
import Highlight from "react-highlight";
2022-11-26 12:36:08 +03:00
import LocalLibraryIcon from "@mui/icons-material/LocalLibrary";
import InputIcon from "@mui/icons-material/Input";
import { DocItem } from "../../types/nix";
import CodeIcon from "@mui/icons-material/Code";
2022-12-09 18:41:59 +03:00
import ReactMarkdown from "react-markdown";
import ExpandLessIcon from "@mui/icons-material/ExpandLess";
2022-12-11 23:22:45 +03:00
import styles from "./preview.module.css";
import rehypeHighlight from "rehype-highlight";
import nix from "highlight.js/lib/languages/nix";
2022-12-12 16:24:16 +03:00
import Link from "next/link";
// import "highlight.js/styles/github-dark.css";
// import "highlight.js/styles/github.css";
2022-11-26 12:36:08 +03:00
interface PreviewProps {
docItem: DocItem;
2022-12-18 19:31:42 +03:00
closeComponent?: React.ReactNode;
handleClose?: () => void;
2022-11-26 12:36:08 +03:00
}
export const Preview = (props: PreviewProps) => {
2022-12-18 19:31:42 +03:00
const { docItem, handleClose, closeComponent = undefined } = props;
const { name, description, category, example, fn_type } = docItem;
2022-12-12 16:24:16 +03:00
const theme = useTheme();
2022-12-12 16:24:16 +03:00
useEffect(() => {
if (theme.palette.mode === "dark") {
// @ts-ignore - dont check type of css module
import("highlight.js/styles/github-dark.css");
} else {
// @ts-ignore - dont check type of css module
import("highlight.js/styles/github.css");
2022-12-09 18:41:59 +03:00
}
2022-12-12 16:24:16 +03:00
}, [theme]);
2022-12-09 18:41:59 +03:00
const prefix = category.split(/([\/.])/gm).at(4) || "builtins";
const libName = category
.match(/(?:[a-zA-Z]*)\.nix/gm)?.[0]
?.replace(".nix", "");
2022-12-12 16:24:16 +03:00
const libDocsRef = `https://nixos.org/manual/nixpkgs/stable/#function-library-lib.${libName}.${name}`;
const builtinsDocsRef = `https://nixos.org/manual/nix/stable/language/builtins.html#builtins-${name}`;
2022-11-26 12:36:08 +03:00
return (
2022-12-03 19:38:50 +03:00
<Box
sx={{
2022-12-12 16:24:16 +03:00
p: { xs: 0.5, md: 1 },
2022-12-03 19:38:50 +03:00
width: "100%",
2022-12-11 23:22:45 +03:00
overflow: "none",
2022-12-03 19:38:50 +03:00
}}
>
2022-12-11 23:22:45 +03:00
<Box
sx={{
display: { md: "flex", xs: "flex" },
flexDirection: { md: "row", xs: "column-reverse" },
width: "100%",
}}
>
<Typography
variant="h4"
2022-12-18 19:31:42 +03:00
sx={{ wordWrap: "normal", lineBreak: "anywhere" }}
2022-12-11 23:22:45 +03:00
>{`${prefix}.${name}`}</Typography>
2022-12-18 19:31:42 +03:00
{closeComponent || (
<Tooltip title="close details">
<IconButton
sx={{
mx: { xs: "auto", md: 1 },
left: { lg: "calc(50% - 2rem)", xs: "unset" },
position: { lg: "absolute", xs: "relative" },
}}
size="small"
onClick={() => handleClose?.()}
>
<ExpandLessIcon fontSize="large" />
</IconButton>
</Tooltip>
)}
2022-12-11 23:22:45 +03:00
</Box>
2022-12-12 16:24:16 +03:00
<List sx={{ width: "100%" }} disablePadding>
<ListItem sx={{ flexDirection: { xs: "column", sm: "row" }, px: 0 }}>
2022-11-26 12:36:08 +03:00
<ListItemIcon>
2022-12-12 16:24:16 +03:00
<Tooltip title={"read docs"}>
<MuiLink sx={{ m: "auto", color: "primary.light" }}>
<Link
href={prefix != "builtins" ? libDocsRef : builtinsDocsRef}
>
<LocalLibraryIcon sx={{ m: "auto" }} />
</Link>
</MuiLink>
</Tooltip>
2022-11-26 12:36:08 +03:00
</ListItemIcon>
<ListItemText
sx={{
overflow: "hidden",
textOverflow: "ellipsis",
2022-12-11 23:22:45 +03:00
alignSelf: "flex-start",
2022-12-12 16:24:16 +03:00
width: "100%",
px: 0,
}}
2022-12-09 18:41:59 +03:00
primaryTypographyProps={{
color: "text.secondary",
fontSize: 14,
}}
secondaryTypographyProps={{
color: "text.primary",
fontSize: "1rem",
component: "div",
2022-12-09 18:41:59 +03:00
}}
2022-12-12 16:24:16 +03:00
primary={
prefix !== "builtins" ? (
<Tooltip title={"browse source code"}>
<MuiLink>
<Link
href={`https://github.com/NixOS/nixpkgs/blob/master/${category.replace(
"./",
""
)}`}
>
{"github:NixOS/nixpkgs/" + category.replace("./", "")}
</Link>
</MuiLink>
</Tooltip>
) : (
"github:NixOS/nix/" + category.replace("./", "")
)
}
2022-12-09 18:41:59 +03:00
secondary={
<Container
2022-12-11 23:22:45 +03:00
component={"div"}
sx={{
ml: "0 !important",
pl: "0 !important",
overflow: "visible",
}}
maxWidth="md"
2022-12-09 18:41:59 +03:00
>
{typeof description === "object"
? description.map((d, idx) => (
<ReactMarkdown
key={idx}
components={{
h1: "h3",
h2: "h4",
h3: "h5",
}}
rehypePlugins={[
[rehypeHighlight, { languages: { nix } }],
]}
>
{d}
</ReactMarkdown>
2022-12-09 18:41:59 +03:00
))
: description && (
<ReactMarkdown
components={{
h1: "h3",
h2: "h4",
h3: "h5",
}}
rehypePlugins={[
[rehypeHighlight, { languages: { nix } }],
]}
>
{description}
</ReactMarkdown>
)}
2022-12-09 18:41:59 +03:00
</Container>
}
2022-11-26 12:36:08 +03:00
/>
</ListItem>
2022-12-12 16:24:16 +03:00
<ListItem sx={{ flexDirection: { xs: "column", sm: "row" }, px: 0 }}>
2022-11-26 12:36:08 +03:00
<ListItemIcon>
2022-12-12 16:24:16 +03:00
<Tooltip title={"browse source code"}>
<MuiLink sx={{ m: "auto", color: "primary.light" }}>
<Link
href={`https://github.com/NixOS/nixpkgs/blob/master/${category.replace(
"./",
""
)}`}
>
<InputIcon sx={{ m: "auto" }} />
</Link>
</MuiLink>
</Tooltip>
2022-11-26 12:36:08 +03:00
</ListItemIcon>
<ListItemText
sx={{
overflow: "hidden",
2022-12-12 16:24:16 +03:00
width: "100%",
textOverflow: "ellipsis",
2022-12-11 23:22:45 +03:00
alignSelf: "flex-start",
}}
2022-12-09 18:41:59 +03:00
primaryTypographyProps={{
color: "text.secondary",
fontSize: 14,
}}
secondaryTypographyProps={{
color: "text.primary",
fontSize: "1rem",
}}
2022-12-12 10:17:07 +03:00
secondary={fn_type || "no type provided yet."}
2022-12-09 18:41:59 +03:00
primary="function signature "
/>
2022-11-26 12:36:08 +03:00
</ListItem>
2022-12-18 19:31:42 +03:00
{example && (
<ListItem
sx={{
backgroundColor: "background.paper",
flexDirection: { xs: "column", sm: "row" },
px: 0,
}}
>
(
2022-12-12 16:24:16 +03:00
<ListItemIcon>
<CodeIcon sx={{ m: "auto" }} />
</ListItemIcon>
2022-12-18 19:31:42 +03:00
)
2022-12-12 16:24:16 +03:00
<ListItemText
sx={{
overflow: "hidden",
textOverflow: "ellipsis",
alignSelf: "flex-start",
width: "100%",
px: 0,
}}
disableTypography
primary={
2022-12-08 01:10:58 +03:00
<Typography sx={{ color: "text.secondary" }}>
Example
</Typography>
2022-12-12 16:24:16 +03:00
}
secondary={
<Box
sx={{
"&.MuiBox-root>pre": {
width: "100%",
},
}}
>
2022-12-11 23:22:45 +03:00
<Highlight className={`nix ${styles.hljs}`}>
2022-12-12 16:24:16 +03:00
{example}
2022-12-11 23:22:45 +03:00
</Highlight>
2022-12-08 01:10:58 +03:00
</Box>
2022-12-12 16:24:16 +03:00
}
/>
2022-12-18 19:31:42 +03:00
</ListItem>
)}
2022-11-26 12:36:08 +03:00
</List>
</Box>
);
};