add: social actions

This commit is contained in:
hsjobeki 2022-12-18 17:31:42 +01:00
parent b2d2d7230a
commit 3425861790
11 changed files with 451 additions and 83 deletions

View File

@ -1,7 +1,23 @@
import { ListItemText, Paper, Stack, Typography } from "@mui/material";
import {
Box,
IconButton,
ListItemText,
Paper,
Stack,
Toolbar,
Tooltip,
Typography,
} from "@mui/material";
import { useMemo } from "react";
import { DocItem } from "../../types/nix";
import { DocItem, NixType } from "../../types/nix";
import { Preview } from "../preview/preview";
import StarIcon from "@mui/icons-material/Star";
import ShareIcon from "@mui/icons-material/Share";
import { useLocalStorage } from "beautiful-react-hooks";
import { useSnackbar } from "notistack";
import StarRateIcon from "@mui/icons-material/StarRate";
import StarBorderIcon from "@mui/icons-material/StarBorder";
import { Key } from "@mui/icons-material";
interface FunctionItemProps {
selected: boolean;
@ -9,9 +25,20 @@ interface FunctionItemProps {
docItem: DocItem;
handleClose: () => void;
}
const getKey = (item: DocItem) => `${item.category}/${item.name}`;
export default function FunctionItem(props: FunctionItemProps) {
const { name, docItem, selected, handleClose } = props;
const { fn_type, category, description } = docItem;
const { enqueueSnackbar } = useSnackbar();
const [favorites, setfavorites] = useLocalStorage<string[]>(
"personal-favorite",
[]
);
const isFavorit = useMemo(
() => favorites.includes(getKey(docItem)),
[docItem, favorites]
);
const descriptionPreview = useMemo(() => {
const getFirstWords = (s: string) => {
const indexOfDot = s.indexOf(".");
@ -29,6 +56,27 @@ export default function FunctionItem(props: FunctionItemProps) {
return "";
}
}, [description]);
const handleShare = () => {
const queries = [];
const key = getKey(docItem);
if (key) {
queries.push(`fn=${key}`);
}
const handle = `https://noogle.dev/preview?${queries.join("&")}`;
navigator.clipboard.writeText(handle);
enqueueSnackbar("link copied to clipboard", { variant: "default" });
};
const handleFavorit = () => {
const key = getKey(docItem);
setfavorites((curr) => {
if (curr.includes(key)) {
return curr.filter((v) => v !== key);
} else {
return [...curr, key];
}
});
};
return (
<Paper
elevation={0}
@ -36,8 +84,9 @@ export default function FunctionItem(props: FunctionItemProps) {
cursor: !selected ? "pointer" : "default",
display: "flex",
justifyContent: "left",
px: { xs: 0, md: 2 },
py: 1,
px: selected ? 0 : { xs: 0, md: 2 },
pt: 1,
mb: 0,
color: selected ? "primary.main" : undefined,
borderColor: selected ? "primary.light" : "none",
borderWidth: 1,
@ -52,6 +101,9 @@ export default function FunctionItem(props: FunctionItemProps) {
<Stack sx={{ width: "100%" }}>
{!selected && (
<>
<Box sx={{ float: "right", position: "absolute", right: 4 }}>
{isFavorit && <StarIcon />}
</Box>
<ListItemText
primary={`${
category.includes(".nix") ? "lib" : "builtins"
@ -68,7 +120,27 @@ export default function FunctionItem(props: FunctionItemProps) {
</Typography>
</>
)}
{selected && <Preview docItem={docItem} handleClose={handleClose} />}
{selected && (
<>
<Preview docItem={docItem} handleClose={handleClose} />
<Toolbar
sx={{
justifyContent: "end",
}}
>
<Tooltip title={`${isFavorit ? "remove" : "add"} favorite`}>
<IconButton onClick={handleFavorit}>
{isFavorit ? <StarIcon /> : <StarBorderIcon />}
</IconButton>
</Tooltip>
<Tooltip title="Share">
<IconButton onClick={handleShare}>
<ShareIcon />
</IconButton>
</Tooltip>
</Toolbar>
</>
)}
</Stack>
</Paper>
);

View File

@ -29,11 +29,12 @@ import Link from "next/link";
interface PreviewProps {
docItem: DocItem;
handleClose: () => void;
closeComponent?: React.ReactNode;
handleClose?: () => void;
}
export const Preview = (props: PreviewProps) => {
const { docItem, handleClose } = props;
const { docItem, handleClose, closeComponent = undefined } = props;
const { name, description, category, example, fn_type } = docItem;
const theme = useTheme();
@ -70,21 +71,23 @@ export const Preview = (props: PreviewProps) => {
>
<Typography
variant="h4"
sx={{ wordWrap: "normal", lineBreak: "" }}
sx={{ wordWrap: "normal", lineBreak: "anywhere" }}
>{`${prefix}.${name}`}</Typography>
<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>
{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>
)}
</Box>
<List sx={{ width: "100%" }} disablePadding>
<ListItem sx={{ flexDirection: { xs: "column", sm: "row" }, px: 0 }}>
@ -212,19 +215,19 @@ export const Preview = (props: PreviewProps) => {
primary="function signature "
/>
</ListItem>
<ListItem
sx={{
backgroundColor: "background.paper",
flexDirection: { xs: "column", sm: "row" },
px: 0,
}}
>
{example && (
{example && (
<ListItem
sx={{
backgroundColor: "background.paper",
flexDirection: { xs: "column", sm: "row" },
px: 0,
}}
>
(
<ListItemIcon>
<CodeIcon sx={{ m: "auto" }} />
</ListItemIcon>
)}
{example && (
)
<ListItemText
sx={{
overflow: "hidden",
@ -253,8 +256,8 @@ export const Preview = (props: PreviewProps) => {
</Box>
}
/>
)}
</ListItem>
</ListItem>
)}
</List>
</Box>
);

View File

@ -1,8 +1,7 @@
import React, { useState, useMemo } from "react";
import React, { useState, useMemo, useEffect } from "react";
import Paper from "@mui/material/Paper";
import InputBase from "@mui/material/InputBase";
import IconButton from "@mui/material/IconButton";
import SearchIcon from "@mui/icons-material/Search";
import ClearIcon from "@mui/icons-material/Clear";
import {
Box,
@ -13,10 +12,14 @@ import {
Grid,
Radio,
RadioGroup,
Tooltip,
Typography,
} from "@mui/material";
import ChevronRightIcon from "@mui/icons-material/ChevronRight";
import { NixType, nixTypes } from "../../types/nix";
import { useRouter } from "next/router";
import ShareIcon from "@mui/icons-material/Share";
import { useSnackbar } from "notistack";
interface SelectOptionProps {
label: string;
@ -77,22 +80,62 @@ const SelectOption = (props: SelectOptionProps) => {
);
};
type Filter = { from: NixType; to: NixType };
export interface SearchInputProps {
handleSearch: (term: string) => void;
handleFilter: (filter: { to: NixType; from: NixType }) => void;
handleFilter: (filter: Filter | ((curr: Filter) => Filter)) => void;
clearSearch: () => void;
placeholder: string;
}
export function SearchInput(props: SearchInputProps) {
const { handleSearch, clearSearch, placeholder, handleFilter } = props;
const { enqueueSnackbar } = useSnackbar();
const [term, setTerm] = useState("");
const [to, setTo] = useState<NixType>("any");
const [from, setFrom] = useState<NixType>("any");
const router = useRouter();
useEffect(() => {
const { query } = router;
if (query?.search) {
if (typeof query.search === "string") {
const search = query.search;
setTerm(search);
handleSearch(search);
}
}
if (query?.to) {
if (typeof query.to === "string") {
const to = query.to as NixType;
setTo(to);
handleFilter((curr) => ({ ...curr, to }));
}
}
if (query?.from) {
if (typeof query.from === "string") {
const from = query.from as NixType;
setFrom(from);
handleFilter((curr) => ({ ...curr, from }));
}
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [router]);
const handleShare = () => {
const queries = [];
if (term) {
queries.push(`search=${term}`);
}
queries.push(`to=${to}&from=${from}`);
const handle = `https://noogle.dev?${queries.join("&")}`;
navigator.clipboard.writeText(handle);
enqueueSnackbar("link copied to clipboard", { variant: "default" });
};
const handleSubmit = React.useRef((input: string) => {
handleSearch(input);
router.query[term] = term;
}).current;
const debouncedSubmit = useMemo(
() => debounce(handleSubmit, 300),
@ -100,7 +143,6 @@ export function SearchInput(props: SearchInputProps) {
);
const _handleFilter = (t: NixType, mode: "from" | "to") => {
console.log({ t, mode });
if (mode === "to") {
setTo(t);
handleFilter({ to: t, from });
@ -156,23 +198,19 @@ export function SearchInput(props: SearchInputProps) {
value={term}
onChange={(e) => handleChange(e)}
/>
<IconButton
type="submit"
onClick={() => handleSubmit(term)}
sx={{
p: 1,
bgcolor: "primary.dark",
color: "common.white",
"&:hover": {
backgroundColor: "primary.main",
opacity: [0.9, 0.8, 0.7],
},
}}
aria-label="search-button"
>
<SearchIcon />
</IconButton>
<Tooltip title="share search result">
<IconButton
sx={{
p: 1,
color: "common.black",
}}
onClick={handleShare}
>
<ShareIcon fontSize="inherit" />
</IconButton>
</Tooltip>
</Paper>
<Box>
<Grid container>
<Grid item xs={12} md={5}>

View File

@ -340,6 +340,20 @@
"type": "github"
}
},
"nixpkgs_4": {
"locked": {
"lastModified": 1671160997,
"narHash": "sha256-fcPZMRjAkUhrfXwoq2RPejfhtPnQ+aI5CTr4x8d0JPs=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "4172cdda7e56a48065475fb98c57b03b83c1fde4",
"type": "github"
},
"original": {
"id": "nixpkgs",
"type": "indirect"
}
},
"poetry2nix": {
"flake": false,
"locked": {
@ -385,7 +399,8 @@
"root": {
"inputs": {
"dream2nix": "dream2nix",
"nixdoc-fork": "nixdoc-fork"
"nixdoc-fork": "nixdoc-fork",
"nixpkgs": "nixpkgs_4"
}
},
"rust-analyzer-src": {

View File

@ -1,9 +1,10 @@
{
inputs.dream2nix.url = "github:nix-community/dream2nix";
inputs.nixdoc-fork.url = "github:hsjobeki/nixdoc";
outputs = inp:
outputs = {self, nixpkgs,...}@inp:
let
system = "x86_64-linux";
pkgs = inp.nixpkgs.legacyPackages.${system};
inherit (builtins.fromJSON (builtins.readFile ./package.json)) name;
in
(inp.dream2nix.lib.makeFlakeOutputs {
@ -31,9 +32,11 @@
'';
};
};
});
# // {
# packages.${system}.nixi = inp.nixdoc-fork.packages.${system}.data;
# };
})
// {
devShells.${system}.default = pkgs.mkShell {
buildInputs = with pkgs; [nodejs-18_x ];
};
};
}

8
models/data.ts Normal file
View File

@ -0,0 +1,8 @@
import { MetaData } from "../types/nix";
import nixLibs from "../models/lib.json";
import nixBuiltins from "../models/builtins.json";
export const data: MetaData = [
...(nixLibs as MetaData),
...(nixBuiltins as MetaData),
].sort((a, b) => a.name.localeCompare(b.name));

192
package-lock.json generated
View File

@ -16,11 +16,12 @@
"@types/node": "18.11.9",
"@types/react": "^18.0.25",
"@types/react-dom": "18.0.8",
"beautiful-react-hooks": "^3.11.2",
"eslint": "8.27.0",
"eslint-config-next": "13.0.2",
"highlight.js": "^11.7.0",
"highlightjs-copy": "^1.0.3",
"next": "13.0.2",
"notistack": "^2.0.8",
"react": "18.2.0",
"react-dom": "18.2.0",
"react-highlight": "^0.15.0",
@ -1262,6 +1263,15 @@
"url": "https://opencollective.com/popperjs"
}
},
"node_modules/@remix-run/router": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.0.5.tgz",
"integrity": "sha512-my0Mycd+jruq/1lQuO5LBB6WTlL/e8DTCYWp44DfMTDcXz8DcTlgF0ISaLsGewt+ctHN+yA8xMq3q/N7uWJPug==",
"peer": true,
"engines": {
"node": ">=14"
}
},
"node_modules/@rushstack/eslint-patch": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.2.0.tgz",
@ -1657,6 +1667,21 @@
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
},
"node_modules/beautiful-react-hooks": {
"version": "3.11.2",
"resolved": "https://registry.npmjs.org/beautiful-react-hooks/-/beautiful-react-hooks-3.11.2.tgz",
"integrity": "sha512-g3pIIZhYfvk1btovwojdMOZ/UjqHi5jqv0TPG0AbQ9B8N8qmGgfgMHPPShelwWevSy7b4VVTmWr1VUJ+QnDR+A==",
"dependencies": {
"lodash.debounce": "^4.0.8",
"lodash.throttle": "^4.1.1"
},
"peerDependencies": {
"react": ">=16.0.0",
"react-dom": ">=16.0.0",
"react-router-dom": ">=5.0.0",
"rxjs": ">=7.0.0"
}
},
"node_modules/brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
@ -2831,11 +2856,6 @@
"node": ">=12.0.0"
}
},
"node_modules/highlightjs-copy": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/highlightjs-copy/-/highlightjs-copy-1.0.3.tgz",
"integrity": "sha512-vXHBmzz7IuJg8f5ixX7qxhfCCDnEQCXRuIzcd7yTblJazZT3ZkaRto0md8IfBu86JdK4VRIdKMubxKt7kwNGfg=="
},
"node_modules/hoist-non-react-statics": {
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz",
@ -3260,11 +3280,21 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/lodash.debounce": {
"version": "4.0.8",
"resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
"integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow=="
},
"node_modules/lodash.merge": {
"version": "4.6.2",
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
"integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="
},
"node_modules/lodash.throttle": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz",
"integrity": "sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ=="
},
"node_modules/loose-envify": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
@ -3915,6 +3945,34 @@
"integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==",
"peer": true
},
"node_modules/notistack": {
"version": "2.0.8",
"resolved": "https://registry.npmjs.org/notistack/-/notistack-2.0.8.tgz",
"integrity": "sha512-/IY14wkFp5qjPgKNvAdfL5Jp6q90+MjgKTPh4c81r/lW70KeuX6b9pE/4f8L4FG31cNudbN9siiFS5ql1aSLRw==",
"dependencies": {
"clsx": "^1.1.0",
"hoist-non-react-statics": "^3.3.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/notistack"
},
"peerDependencies": {
"@emotion/react": "^11.4.1",
"@emotion/styled": "^11.3.0",
"@mui/material": "^5.0.0",
"react": "^16.8.0 || ^17.0.0 || ^18.0.0",
"react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0"
},
"peerDependenciesMeta": {
"@emotion/react": {
"optional": true
},
"@emotion/styled": {
"optional": true
}
}
},
"node_modules/object-assign": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
@ -4302,6 +4360,38 @@
"resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz",
"integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w=="
},
"node_modules/react-router": {
"version": "6.4.5",
"resolved": "https://registry.npmjs.org/react-router/-/react-router-6.4.5.tgz",
"integrity": "sha512-1RQJ8bM70YEumHIlNUYc6mFfUDoWa5EgPDenK/fq0bxD8DYpQUi/S6Zoft+9DBrh2xmtg92N5HMAJgGWDhKJ5Q==",
"peer": true,
"dependencies": {
"@remix-run/router": "1.0.5"
},
"engines": {
"node": ">=14"
},
"peerDependencies": {
"react": ">=16.8"
}
},
"node_modules/react-router-dom": {
"version": "6.4.5",
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.4.5.tgz",
"integrity": "sha512-a7HsgikBR0wNfroBHcZUCd9+mLRqZS8R5U1Z1mzLWxFXEkUT3vR1XXmSIVoVpxVX8Bar0nQYYYc9Yipq8dWwAA==",
"peer": true,
"dependencies": {
"@remix-run/router": "1.0.5",
"react-router": "6.4.5"
},
"engines": {
"node": ">=14"
},
"peerDependencies": {
"react": ">=16.8",
"react-dom": ">=16.8"
}
},
"node_modules/react-transition-group": {
"version": "4.4.5",
"resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz",
@ -4463,6 +4553,21 @@
"queue-microtask": "^1.2.2"
}
},
"node_modules/rxjs": {
"version": "7.8.0",
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.0.tgz",
"integrity": "sha512-F2+gxDshqmIub1KdvZkaEfGDwLNpPvk9Fs6LD/MyQxNgMds/WH9OdDDXOmxUZpME+iSK3rQCctkL0DYyytUqMg==",
"peer": true,
"dependencies": {
"tslib": "^2.1.0"
}
},
"node_modules/rxjs/node_modules/tslib": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz",
"integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==",
"peer": true
},
"node_modules/sade": {
"version": "1.8.1",
"resolved": "https://registry.npmjs.org/sade/-/sade-1.8.1.tgz",
@ -5885,6 +5990,12 @@
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.6.tgz",
"integrity": "sha512-50/17A98tWUfQ176raKiOGXuYpLyyVMkxxG6oylzL3BPOlA6ADGdK7EYunSa4I064xerltq9TGXs8HmOk5E+vw=="
},
"@remix-run/router": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.0.5.tgz",
"integrity": "sha512-my0Mycd+jruq/1lQuO5LBB6WTlL/e8DTCYWp44DfMTDcXz8DcTlgF0ISaLsGewt+ctHN+yA8xMq3q/N7uWJPug==",
"peer": true
},
"@rushstack/eslint-patch": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.2.0.tgz",
@ -6178,6 +6289,15 @@
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
},
"beautiful-react-hooks": {
"version": "3.11.2",
"resolved": "https://registry.npmjs.org/beautiful-react-hooks/-/beautiful-react-hooks-3.11.2.tgz",
"integrity": "sha512-g3pIIZhYfvk1btovwojdMOZ/UjqHi5jqv0TPG0AbQ9B8N8qmGgfgMHPPShelwWevSy7b4VVTmWr1VUJ+QnDR+A==",
"requires": {
"lodash.debounce": "^4.0.8",
"lodash.throttle": "^4.1.1"
}
},
"brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
@ -7030,11 +7150,6 @@
"resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-11.7.0.tgz",
"integrity": "sha512-1rRqesRFhMO/PRF+G86evnyJkCgaZFOI+Z6kdj15TA18funfoqJXvgPCLSf0SWq3SRfg1j3HlDs8o4s3EGq1oQ=="
},
"highlightjs-copy": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/highlightjs-copy/-/highlightjs-copy-1.0.3.tgz",
"integrity": "sha512-vXHBmzz7IuJg8f5ixX7qxhfCCDnEQCXRuIzcd7yTblJazZT3ZkaRto0md8IfBu86JdK4VRIdKMubxKt7kwNGfg=="
},
"hoist-non-react-statics": {
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz",
@ -7322,11 +7437,21 @@
"p-locate": "^5.0.0"
}
},
"lodash.debounce": {
"version": "4.0.8",
"resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
"integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow=="
},
"lodash.merge": {
"version": "4.6.2",
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
"integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="
},
"lodash.throttle": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz",
"integrity": "sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ=="
},
"loose-envify": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
@ -7694,6 +7819,15 @@
"integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==",
"peer": true
},
"notistack": {
"version": "2.0.8",
"resolved": "https://registry.npmjs.org/notistack/-/notistack-2.0.8.tgz",
"integrity": "sha512-/IY14wkFp5qjPgKNvAdfL5Jp6q90+MjgKTPh4c81r/lW70KeuX6b9pE/4f8L4FG31cNudbN9siiFS5ql1aSLRw==",
"requires": {
"clsx": "^1.1.0",
"hoist-non-react-statics": "^3.3.0"
}
},
"object-assign": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
@ -7956,6 +8090,25 @@
}
}
},
"react-router": {
"version": "6.4.5",
"resolved": "https://registry.npmjs.org/react-router/-/react-router-6.4.5.tgz",
"integrity": "sha512-1RQJ8bM70YEumHIlNUYc6mFfUDoWa5EgPDenK/fq0bxD8DYpQUi/S6Zoft+9DBrh2xmtg92N5HMAJgGWDhKJ5Q==",
"peer": true,
"requires": {
"@remix-run/router": "1.0.5"
}
},
"react-router-dom": {
"version": "6.4.5",
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.4.5.tgz",
"integrity": "sha512-a7HsgikBR0wNfroBHcZUCd9+mLRqZS8R5U1Z1mzLWxFXEkUT3vR1XXmSIVoVpxVX8Bar0nQYYYc9Yipq8dWwAA==",
"peer": true,
"requires": {
"@remix-run/router": "1.0.5",
"react-router": "6.4.5"
}
},
"react-transition-group": {
"version": "4.4.5",
"resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz",
@ -8056,6 +8209,23 @@
"queue-microtask": "^1.2.2"
}
},
"rxjs": {
"version": "7.8.0",
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.0.tgz",
"integrity": "sha512-F2+gxDshqmIub1KdvZkaEfGDwLNpPvk9Fs6LD/MyQxNgMds/WH9OdDDXOmxUZpME+iSK3rQCctkL0DYyytUqMg==",
"peer": true,
"requires": {
"tslib": "^2.1.0"
},
"dependencies": {
"tslib": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz",
"integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==",
"peer": true
}
}
},
"sade": {
"version": "1.8.1",
"resolved": "https://registry.npmjs.org/sade/-/sade-1.8.1.tgz",

View File

@ -18,11 +18,12 @@
"@types/node": "18.11.9",
"@types/react": "^18.0.25",
"@types/react-dom": "18.0.8",
"beautiful-react-hooks": "^3.11.2",
"eslint": "8.27.0",
"eslint-config-next": "13.0.2",
"highlight.js": "^11.7.0",
"highlightjs-copy": "^1.0.3",
"next": "13.0.2",
"notistack": "^2.0.8",
"react": "18.2.0",
"react-dom": "18.2.0",
"react-highlight": "^0.15.0",

View File

@ -3,6 +3,7 @@ import type { AppProps } from "next/app";
import { CacheProvider, EmotionCache } from "@emotion/react";
import { ThemeProvider, CssBaseline, createTheme } from "@mui/material";
import useMediaQuery from "@mui/material/useMediaQuery";
import { SnackbarProvider } from "notistack";
import "@fontsource/roboto/300.css";
import "@fontsource/roboto/400.css";
@ -46,7 +47,12 @@ const MyApp: React.FunctionComponent<MyAppProps> = (props) => {
<CacheProvider value={emotionCache}>
<ThemeProvider theme={userPrefersDarkmode ? darkTheme : lightTheme}>
<CssBaseline />
{getContent()}
<SnackbarProvider
anchorOrigin={{ vertical: "bottom", horizontal: "center" }}
maxSnack={1}
>
{getContent()}
</SnackbarProvider>
</ThemeProvider>
</CacheProvider>
</>

View File

@ -1,15 +1,10 @@
import { BasicList, BasicListItem } from "../components/basicList";
import { useState, useMemo } from "react";
import { useState, useMemo, useEffect } from "react";
import { Box } from "@mui/material";
import FunctionItem from "../components/functionItem/functionItem";
import { NixType, nixTypes, MetaData, DocItem } from "../types/nix";
import nixLibs from "../models/lib.json";
import nixBuiltins from "../models/builtins.json";
const data: MetaData = [
...(nixLibs as MetaData),
...(nixBuiltins as MetaData),
].sort((a, b) => a.name.localeCompare(b.name));
import { data } from "../models/data";
import { useRouter } from "next/router";
function pipe<T>(...fns: ((arr: T) => T)[]) {
return (x: T) => fns.reduce((v, f) => f(v), x);
@ -107,8 +102,10 @@ export default function FunctionsPage() {
to: "any",
from: "any",
});
const router = useRouter();
const handleSelect = (key: string) => {
console.log({ key });
setSelected((curr: string | null) => {
if (curr === key) {
return null;
@ -127,8 +124,20 @@ export default function FunctionsPage() {
setTerm(term);
};
const handleFilter = (filter: { from: NixType; to: NixType }) => {
setFilter(filter);
// useEffect(() => {
// const query = [];
// if (term) {
// query.push(`search=${term}`);
// }
// if (filter) {
// query.push(`to=${filter.to}&from=${filter.from}`);
// }
// router.push(`?${query.join("&")}`);
// }, [filter, term]);
type Filter = { from: NixType; to: NixType };
const handleFilter = (newFilter: Filter | ((curr: Filter) => Filter)) => {
setFilter(newFilter);
};
const getKey = (item: DocItem) => `${item.category}/${item.name}`;

43
pages/preview.tsx Normal file
View File

@ -0,0 +1,43 @@
import { IconButton, Paper, Tooltip } from "@mui/material";
import { useRouter } from "next/router";
import { useEffect, useState } from "react";
import { Preview } from "../components/preview/preview";
import { data } from "../models/data";
import { DocItem } from "../types/nix";
import ArrowBackIosIcon from "@mui/icons-material/ArrowBackIos";
const getKey = (item: DocItem) => `${item.category}/${item.name}`;
export default function PreviewPage() {
const router = useRouter();
const [item, setItem] = useState<DocItem | null>(null);
useEffect(() => {
const { query } = router;
if (query?.fn) {
if (typeof query.fn === "string") {
const name = query.fn;
setItem(data.find((d) => getKey(d) === name) || null);
}
}
}, [router]);
return (
item && (
<>
<Paper sx={{ py: 4 }} elevation={0}>
<Tooltip title="back to list">
<IconButton
sx={{
mx: 3,
}}
size="small"
onClick={() => router.push("/")}
>
<ArrowBackIosIcon fontSize="large" />
</IconButton>
</Tooltip>
<Preview docItem={item} closeComponent={<span></span>} />
</Paper>
</>
)
);
}