mirror of
https://github.com/nix-community/noogle.git
synced 2024-11-28 11:32:19 +03:00
INIT: first prototype of frontend
This commit is contained in:
commit
c51722be2d
3
.eslintrc.json
Normal file
3
.eslintrc.json
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"extends": "next/core-web-vitals"
|
||||||
|
}
|
44
.gitignore
vendored
Normal file
44
.gitignore
vendored
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||||
|
|
||||||
|
# dependencies
|
||||||
|
/node_modules
|
||||||
|
/.pnp
|
||||||
|
.pnp.js
|
||||||
|
|
||||||
|
# testing
|
||||||
|
/coverage
|
||||||
|
|
||||||
|
# nix
|
||||||
|
.direnv/
|
||||||
|
result
|
||||||
|
result-*
|
||||||
|
|
||||||
|
|
||||||
|
# next.js
|
||||||
|
/.next/
|
||||||
|
/out/
|
||||||
|
|
||||||
|
# production
|
||||||
|
/build
|
||||||
|
|
||||||
|
# misc
|
||||||
|
.DS_Store
|
||||||
|
*.pem
|
||||||
|
result
|
||||||
|
result-*
|
||||||
|
|
||||||
|
# debug
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
.pnpm-debug.log*
|
||||||
|
|
||||||
|
# local env files
|
||||||
|
.env*.local
|
||||||
|
|
||||||
|
# vercel
|
||||||
|
.vercel
|
||||||
|
|
||||||
|
# typescript
|
||||||
|
*.tsbuildinfo
|
||||||
|
next-env.d.ts
|
27
README.md
Normal file
27
README.md
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
# Static page with nextjs example
|
||||||
|
|
||||||
|
- Generates a static page
|
||||||
|
- Includes custom Image loader for static page generation
|
||||||
|
|
||||||
|
## Build
|
||||||
|
|
||||||
|
> ### ! The build step is completly independent of develop step and can be run right after checkout
|
||||||
|
|
||||||
|
`nix build .#`
|
||||||
|
|
||||||
|
This should create to following result:
|
||||||
|
|
||||||
|
- static/
|
||||||
|
- __index.html__
|
||||||
|
- favicon.ico
|
||||||
|
- 404.html
|
||||||
|
- vercel-svg
|
||||||
|
- _next/
|
||||||
|
- static/...
|
||||||
|
- ...
|
||||||
|
|
||||||
|
## Develop
|
||||||
|
|
||||||
|
`nix develop`
|
||||||
|
|
||||||
|
This command creates the node_modules folder with all needed dependencies
|
103
components/basicList/basicList.spec.tsx
Normal file
103
components/basicList/basicList.spec.tsx
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
import "@testing-library/jest-dom";
|
||||||
|
// TODO: important mock zustand!
|
||||||
|
// State from previous tests leaking into other test cases because zustand is never reset in its own
|
||||||
|
|
||||||
|
import * as React from "react";
|
||||||
|
import { render, screen, act } from "@testing-library/react";
|
||||||
|
import mockAxios from "jest-mock-axios";
|
||||||
|
import userEvent from "@testing-library/user-event";
|
||||||
|
|
||||||
|
import { ImageList } from "./";
|
||||||
|
import { QueryClient, QueryClientProvider } from "react-query";
|
||||||
|
import { SnackbarProvider } from "notistack";
|
||||||
|
|
||||||
|
const queryClient = new QueryClient();
|
||||||
|
|
||||||
|
const Wrapper = (element: React.ReactNode) => (
|
||||||
|
<QueryClientProvider client={queryClient}>
|
||||||
|
<SnackbarProvider>{element}</SnackbarProvider>
|
||||||
|
</QueryClientProvider>
|
||||||
|
);
|
||||||
|
|
||||||
|
const getImagesResp = [
|
||||||
|
{
|
||||||
|
filename: "testfile.iso",
|
||||||
|
hash: "3993d64556f3ae803986f6d1c2debaa8f5a2a77da70cc35f86af6f99c849fe80",
|
||||||
|
modify_time: "2022-07-28T07:45:32.331998395Z",
|
||||||
|
size_bytes: 513,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
filename: "full.img",
|
||||||
|
hash: "85c6a11c928611caff965aa2fc267b51ad3fc06657d0ee67ae00fec1711e81ef",
|
||||||
|
modify_time: "2022-07-29T07:33:20.075281078Z",
|
||||||
|
size_bytes: 1024 * 1024 * 1024,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
filename: "small.img",
|
||||||
|
hash: "e8edbf1bb6121a38e8ee3a60e34a31887955bc9a292e9ef3bd598e8ccb7fef5a",
|
||||||
|
modify_time: "2022-07-29T07:34:10.442184606Z",
|
||||||
|
size_bytes: 1,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
describe("render imageList", () => {
|
||||||
|
afterEach(() => {
|
||||||
|
mockAxios.reset();
|
||||||
|
jest.clearAllMocks();
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await act(async () => {
|
||||||
|
mockAxios.get.mockResolvedValue({ data: getImagesResp });
|
||||||
|
render(Wrapper(<ImageList />), {});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test("list is shown & has proper length", async () => {
|
||||||
|
const list = await screen.getByRole("list", { name: "image-list" });
|
||||||
|
const listItems = await screen.getAllByRole("listitem", {
|
||||||
|
name: "image-entry-item",
|
||||||
|
});
|
||||||
|
expect(list).toBeVisible();
|
||||||
|
expect(listItems).toHaveLength(getImagesResp.length);
|
||||||
|
expect(mockAxios.get).toBeCalledTimes(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("search: a term", async () => {
|
||||||
|
const searchInput = await screen.getByRole("textbox", {
|
||||||
|
name: "search-input",
|
||||||
|
});
|
||||||
|
const searchButton = await screen.getByRole("button", {
|
||||||
|
name: "search-button",
|
||||||
|
});
|
||||||
|
await userEvent.type(searchInput, ".img");
|
||||||
|
await userEvent.click(searchButton);
|
||||||
|
|
||||||
|
/*
|
||||||
|
search for filename with ".img" in it
|
||||||
|
-> should yield:
|
||||||
|
[ "full.img", "small.img" ]
|
||||||
|
*/
|
||||||
|
const listItems = await screen.getAllByRole("listitem", {
|
||||||
|
name: "image-entry-item",
|
||||||
|
});
|
||||||
|
expect(listItems).toHaveLength(2);
|
||||||
|
expect(listItems[0]).toHaveTextContent("full.img");
|
||||||
|
expect(listItems[1]).toHaveTextContent("small.img");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("delete an image", async () => {
|
||||||
|
const deleteButtons = await screen.getAllByRole("button", {
|
||||||
|
name: "delete-image",
|
||||||
|
});
|
||||||
|
|
||||||
|
const firstDeleteButton = deleteButtons?.[0];
|
||||||
|
|
||||||
|
expect(firstDeleteButton).toBeEnabled();
|
||||||
|
|
||||||
|
await userEvent.click(firstDeleteButton);
|
||||||
|
|
||||||
|
//TODO: dont have delete functionality yet
|
||||||
|
// expect(mockedDeleteFn).toBeCalled();
|
||||||
|
});
|
||||||
|
});
|
175
components/basicList/basicList.tsx
Normal file
175
components/basicList/basicList.tsx
Normal file
@ -0,0 +1,175 @@
|
|||||||
|
import React, { useState } from "react";
|
||||||
|
import {
|
||||||
|
Box,
|
||||||
|
IconButton,
|
||||||
|
List,
|
||||||
|
ListItem,
|
||||||
|
Pagination,
|
||||||
|
Stack,
|
||||||
|
Typography,
|
||||||
|
Grid,
|
||||||
|
} from "@mui/material";
|
||||||
|
import { BasicDataViewProps, NixType } from "../../types/basicDataView";
|
||||||
|
import { SearchInput } from "../searchInput";
|
||||||
|
import Radio from "@mui/material/Radio";
|
||||||
|
import RadioGroup from "@mui/material/RadioGroup";
|
||||||
|
import FormControlLabel from "@mui/material/FormControlLabel";
|
||||||
|
import FormControl from "@mui/material/FormControl";
|
||||||
|
import FormLabel from "@mui/material/FormLabel";
|
||||||
|
import ClearIcon from "@mui/icons-material/Clear";
|
||||||
|
import ChevronRightIcon from "@mui/icons-material/ChevronRight";
|
||||||
|
|
||||||
|
export type BasicListItem = {
|
||||||
|
item: React.ReactNode;
|
||||||
|
key: string;
|
||||||
|
};
|
||||||
|
export type BasicListProps = BasicDataViewProps & {
|
||||||
|
handleFilter: (t: NixType, mode: "from" | "to") => void;
|
||||||
|
preview: React.ReactNode;
|
||||||
|
};
|
||||||
|
|
||||||
|
interface SelectOptionProps {
|
||||||
|
label: string;
|
||||||
|
handleChange: (value: string) => void;
|
||||||
|
options: {
|
||||||
|
value: string;
|
||||||
|
label: string;
|
||||||
|
}[];
|
||||||
|
}
|
||||||
|
|
||||||
|
const SelectOption = (props: SelectOptionProps) => {
|
||||||
|
const { label, handleChange, options } = props;
|
||||||
|
const [value, setValue] = React.useState<NixType>("any");
|
||||||
|
|
||||||
|
const _handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
|
const newVal = (event.target as HTMLInputElement).value as NixType;
|
||||||
|
setValue(newVal);
|
||||||
|
handleChange(newVal);
|
||||||
|
};
|
||||||
|
const handleClear = () => {
|
||||||
|
setValue("any");
|
||||||
|
handleChange("any");
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<FormControl>
|
||||||
|
<FormLabel>
|
||||||
|
<Box>
|
||||||
|
<IconButton
|
||||||
|
// disabled={value === ""}
|
||||||
|
aria-label="clear-button"
|
||||||
|
onClick={handleClear}
|
||||||
|
>
|
||||||
|
<ClearIcon />
|
||||||
|
</IconButton>
|
||||||
|
{label}
|
||||||
|
</Box>
|
||||||
|
</FormLabel>
|
||||||
|
|
||||||
|
<RadioGroup sx={{ pl: 1.5 }} value={value} onChange={_handleChange}>
|
||||||
|
{options.map(({ value, label }) => (
|
||||||
|
<FormControlLabel
|
||||||
|
key={value}
|
||||||
|
value={value}
|
||||||
|
control={<Radio />}
|
||||||
|
label={label}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</RadioGroup>
|
||||||
|
</FormControl>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export function BasicList(props: BasicListProps) {
|
||||||
|
const { items, pageCount = 1, handleSearch, handleFilter, preview } = props;
|
||||||
|
// const [from, setFrom] = useState<NixType>("any");
|
||||||
|
// const [to, setTo] = useState<NixType>("any");
|
||||||
|
|
||||||
|
const [page, setPage] = useState(1);
|
||||||
|
|
||||||
|
const [searchTerm, setSearchTerm] = useState("");
|
||||||
|
|
||||||
|
const handlePageChange = (
|
||||||
|
_event: React.ChangeEvent<unknown>,
|
||||||
|
value: number
|
||||||
|
) => {
|
||||||
|
setPage(value);
|
||||||
|
};
|
||||||
|
|
||||||
|
const _handleFilter = (t: NixType, mode: "from" | "to") => {
|
||||||
|
handleFilter(t, mode);
|
||||||
|
setPage(1);
|
||||||
|
};
|
||||||
|
|
||||||
|
const _handleSearch = (term: string) => {
|
||||||
|
handleSearch && handleSearch(term);
|
||||||
|
setSearchTerm(term);
|
||||||
|
setPage(1);
|
||||||
|
};
|
||||||
|
const nixTypes: NixType[] = [
|
||||||
|
"any",
|
||||||
|
"attrset",
|
||||||
|
"list",
|
||||||
|
"string",
|
||||||
|
"bool",
|
||||||
|
"int",
|
||||||
|
];
|
||||||
|
return (
|
||||||
|
<Stack>
|
||||||
|
<SearchInput
|
||||||
|
placeholder="search nix functions"
|
||||||
|
handleSearch={_handleSearch}
|
||||||
|
clearSearch={() => _handleSearch("")}
|
||||||
|
/>
|
||||||
|
<Box>
|
||||||
|
<Grid container>
|
||||||
|
<Grid item xs={3}>
|
||||||
|
<Stack direction="row">
|
||||||
|
<SelectOption
|
||||||
|
label="from type"
|
||||||
|
handleChange={(value) => {
|
||||||
|
_handleFilter(value as NixType, "from");
|
||||||
|
}}
|
||||||
|
options={nixTypes.map((v) => ({ value: v, label: v }))}
|
||||||
|
/>
|
||||||
|
<Typography
|
||||||
|
sx={{
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "column",
|
||||||
|
justifyContent: "center",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<ChevronRightIcon />
|
||||||
|
</Typography>
|
||||||
|
<SelectOption
|
||||||
|
label="to type"
|
||||||
|
handleChange={(value) => {
|
||||||
|
_handleFilter(value as NixType, "to");
|
||||||
|
}}
|
||||||
|
options={nixTypes.map((v) => ({ value: v, label: v }))}
|
||||||
|
/>
|
||||||
|
</Stack>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={9}>
|
||||||
|
{preview}
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</Box>
|
||||||
|
<List aria-label="basic-list" sx={{ pt: 0 }}>
|
||||||
|
{items.map(({ item, key }) => (
|
||||||
|
<ListItem key={key} aria-label={`item-${key}`} sx={{ px: 0 }}>
|
||||||
|
{item}
|
||||||
|
</ListItem>
|
||||||
|
))}
|
||||||
|
</List>
|
||||||
|
|
||||||
|
<Pagination
|
||||||
|
sx={{ display: "flex", justifyContent: "center", mt: 1, mb: 10 }}
|
||||||
|
count={pageCount}
|
||||||
|
color="primary"
|
||||||
|
page={page}
|
||||||
|
onChange={handlePageChange}
|
||||||
|
/>
|
||||||
|
</Stack>
|
||||||
|
);
|
||||||
|
}
|
2
components/basicList/index.tsx
Normal file
2
components/basicList/index.tsx
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
export { BasicList } from "./basicList";
|
||||||
|
export type { BasicListProps, BasicListItem } from "./basicList";
|
40
components/functionItem/functionItem.tsx
Normal file
40
components/functionItem/functionItem.tsx
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
import {
|
||||||
|
Box,
|
||||||
|
Card,
|
||||||
|
ListItemText,
|
||||||
|
Paper,
|
||||||
|
Stack,
|
||||||
|
Typography,
|
||||||
|
} from "@mui/material";
|
||||||
|
|
||||||
|
interface FunctionItemProps {
|
||||||
|
selected: boolean;
|
||||||
|
name: String;
|
||||||
|
info: {
|
||||||
|
"attr-path": String;
|
||||||
|
source: String;
|
||||||
|
from: String;
|
||||||
|
to: String;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
export default function FunctionItem(props: FunctionItemProps) {
|
||||||
|
const { name, info, selected } = props;
|
||||||
|
return (
|
||||||
|
<Paper
|
||||||
|
elevation={0}
|
||||||
|
sx={{
|
||||||
|
display: "flex",
|
||||||
|
justifyContent: "left",
|
||||||
|
color: selected ? "primary.main" : undefined,
|
||||||
|
borderColor: selected ? "action.selected" : "none",
|
||||||
|
borderWidth: 1,
|
||||||
|
borderStyle: selected ? "solid" : "none",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Stack>
|
||||||
|
<ListItemText primary={name} secondary={info["attr-path"]} />
|
||||||
|
<Typography>{`${info.from} -> ${info.to} `}</Typography>
|
||||||
|
</Stack>
|
||||||
|
</Paper>
|
||||||
|
);
|
||||||
|
}
|
10
components/image/image.tsx
Normal file
10
components/image/image.tsx
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import NextImage, { ImageLoaderProps, ImageProps } from "next/image";
|
||||||
|
|
||||||
|
// opt-out of image optimization, no-op
|
||||||
|
const customLoader = ({ src }: ImageLoaderProps) => {
|
||||||
|
return src;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function Image(props: ImageProps) {
|
||||||
|
return <NextImage {...props} loader={customLoader} />;
|
||||||
|
}
|
1
components/image/index.tsx
Normal file
1
components/image/index.tsx
Normal file
@ -0,0 +1 @@
|
|||||||
|
export { Image } from "./image";
|
1
components/layout/index.ts
Normal file
1
components/layout/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export { Layout } from "./layout"
|
42
components/layout/layout.tsx
Normal file
42
components/layout/layout.tsx
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
import { Box, Typography, Container, Link } from "@mui/material";
|
||||||
|
// import Link from "next/link";
|
||||||
|
|
||||||
|
export interface LayoutProps {
|
||||||
|
children: React.ReactNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function Layout(props: LayoutProps) {
|
||||||
|
const { children } = props;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<header>
|
||||||
|
<Box sx={{ p: 2, backgroundColor: "primary.main" }}>
|
||||||
|
<Typography variant="h1" sx={{ textAlign: "center", color: "#fff" }}>
|
||||||
|
{`noog\u03BBe`}
|
||||||
|
</Typography>
|
||||||
|
</Box>
|
||||||
|
</header>
|
||||||
|
<main>
|
||||||
|
<Container sx={{ pt: 0 }} maxWidth="xl">
|
||||||
|
{children}
|
||||||
|
</Container>
|
||||||
|
</main>
|
||||||
|
<footer
|
||||||
|
style={{
|
||||||
|
position: "fixed",
|
||||||
|
bottom: 0,
|
||||||
|
display: "flex",
|
||||||
|
justifyContent: "center",
|
||||||
|
width: "100%",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Powered by{" "}
|
||||||
|
<Link sx={{ ml: 1 }} href="https://oceansprint.org/">
|
||||||
|
{" "}
|
||||||
|
OceanSprint
|
||||||
|
</Link>
|
||||||
|
</footer>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
55
components/preview/preview.tsx
Normal file
55
components/preview/preview.tsx
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
import {
|
||||||
|
Box,
|
||||||
|
Link,
|
||||||
|
List,
|
||||||
|
ListItem,
|
||||||
|
ListItemIcon,
|
||||||
|
ListItemSecondaryAction,
|
||||||
|
ListItemText,
|
||||||
|
Typography,
|
||||||
|
} from "@mui/material";
|
||||||
|
import { info } from "console";
|
||||||
|
import { FuncData } from "../../pages";
|
||||||
|
import LocalLibraryIcon from "@mui/icons-material/LocalLibrary";
|
||||||
|
import InputIcon from "@mui/icons-material/Input";
|
||||||
|
import OutputIcon from "@mui/icons-material/Output";
|
||||||
|
|
||||||
|
interface PreviewProps {
|
||||||
|
func: FuncData;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const Preview = (props: PreviewProps) => {
|
||||||
|
const { func } = props;
|
||||||
|
return (
|
||||||
|
<Box sx={{ p: 1, width: "100%" }}>
|
||||||
|
<Typography variant="h2">{func.name}</Typography>
|
||||||
|
<List sx={{ width: "100%" }}>
|
||||||
|
<ListItem>
|
||||||
|
<ListItemIcon>
|
||||||
|
<LocalLibraryIcon />
|
||||||
|
</ListItemIcon>
|
||||||
|
<ListItemText
|
||||||
|
primary={func.info["attr-path"]}
|
||||||
|
secondary={func.info["doc-url"]}
|
||||||
|
/>
|
||||||
|
<ListItemSecondaryAction>
|
||||||
|
<Link href={func.info["doc-url"]}>View Docs</Link>
|
||||||
|
</ListItemSecondaryAction>
|
||||||
|
</ListItem>
|
||||||
|
<ListItem>
|
||||||
|
<ListItemIcon>
|
||||||
|
<InputIcon />
|
||||||
|
</ListItemIcon>
|
||||||
|
<ListItemText primary={func.info.from} secondary="argument type" />
|
||||||
|
</ListItem>
|
||||||
|
<ListItem>
|
||||||
|
<ListItemIcon>
|
||||||
|
<OutputIcon />
|
||||||
|
</ListItemIcon>
|
||||||
|
<ListItemText primary={func.info.to} secondary="return type" />
|
||||||
|
</ListItem>
|
||||||
|
<ListItem></ListItem>
|
||||||
|
</List>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
};
|
1
components/searchInput/index.tsx
Normal file
1
components/searchInput/index.tsx
Normal file
@ -0,0 +1 @@
|
|||||||
|
export { SearchInput } from "./searchInput";
|
56
components/searchInput/searchInput.spec.tsx
Normal file
56
components/searchInput/searchInput.spec.tsx
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
import "@testing-library/jest-dom";
|
||||||
|
import * as React from "react";
|
||||||
|
import { render, screen } from "@testing-library/react";
|
||||||
|
import userEvent from "@testing-library/user-event";
|
||||||
|
import { SearchInput } from "./";
|
||||||
|
|
||||||
|
describe("render search", () => {
|
||||||
|
const mockedSearch = jest.fn();
|
||||||
|
mockedSearch.mockImplementation((term: string) => {
|
||||||
|
return term;
|
||||||
|
});
|
||||||
|
const mockedClear = jest.fn();
|
||||||
|
mockedClear.mockImplementation(() => {
|
||||||
|
return undefined;
|
||||||
|
});
|
||||||
|
beforeEach(() => {
|
||||||
|
render(
|
||||||
|
<SearchInput
|
||||||
|
handleSearch={mockedSearch}
|
||||||
|
clearSearch={mockedClear}
|
||||||
|
placeholder={"Search"}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("renders all elements from the searchbar", async () => {
|
||||||
|
const inputBar = screen.getByRole("textbox");
|
||||||
|
const clearButton = screen.getByRole("button", { name: "clear-button" });
|
||||||
|
const searchButton = screen.getByRole("button", { name: "search-button" });
|
||||||
|
expect(inputBar).toBeVisible();
|
||||||
|
expect(searchButton).toBeVisible();
|
||||||
|
expect(clearButton).toBeVisible();
|
||||||
|
const term = "search for term";
|
||||||
|
await userEvent.type(inputBar, term);
|
||||||
|
await userEvent.click(searchButton);
|
||||||
|
expect(mockedSearch).toBeCalledWith(term);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("search for a term", async () => {
|
||||||
|
const inputBar = screen.getByRole("textbox");
|
||||||
|
const searchButton = screen.getByRole("button", { name: "search-button" });
|
||||||
|
const term = "search for term";
|
||||||
|
await userEvent.type(inputBar, term);
|
||||||
|
await userEvent.click(searchButton);
|
||||||
|
expect(mockedSearch).toBeCalledWith(term);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("clearing search", async () => {
|
||||||
|
const inputBar = screen.getByRole("textbox");
|
||||||
|
const clearButton = screen.getByRole("button", { name: "clear-button" });
|
||||||
|
const term = "search for term";
|
||||||
|
await userEvent.type(inputBar, term);
|
||||||
|
await userEvent.click(clearButton);
|
||||||
|
expect(mockedClear).toBeCalled();
|
||||||
|
});
|
||||||
|
});
|
84
components/searchInput/searchInput.tsx
Normal file
84
components/searchInput/searchInput.tsx
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
import React, { useState, useMemo } 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 { debounce } from "@mui/material";
|
||||||
|
|
||||||
|
export interface SearchInputProps {
|
||||||
|
handleSearch: (term: string) => void;
|
||||||
|
clearSearch: () => void;
|
||||||
|
placeholder: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function SearchInput(props: SearchInputProps) {
|
||||||
|
const { handleSearch, clearSearch, placeholder } = props;
|
||||||
|
|
||||||
|
const [term, setTerm] = useState("");
|
||||||
|
|
||||||
|
const handleSubmit = React.useRef((input: string) => {
|
||||||
|
handleSearch(input);
|
||||||
|
}).current;
|
||||||
|
const debouncedSubmit = useMemo(
|
||||||
|
() => debounce(handleSubmit, 300),
|
||||||
|
[handleSubmit]
|
||||||
|
);
|
||||||
|
|
||||||
|
const handleClear = () => {
|
||||||
|
setTerm("");
|
||||||
|
clearSearch();
|
||||||
|
};
|
||||||
|
const handleChange = (
|
||||||
|
e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>
|
||||||
|
) => {
|
||||||
|
setTerm(e.target.value);
|
||||||
|
debouncedSubmit(e.target.value);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Paper
|
||||||
|
component="form"
|
||||||
|
elevation={0}
|
||||||
|
sx={{
|
||||||
|
width: "100%",
|
||||||
|
p: 1,
|
||||||
|
my: 2,
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
}}
|
||||||
|
onSubmit={(e: React.FormEvent) => {
|
||||||
|
e.preventDefault();
|
||||||
|
handleSubmit(term);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<IconButton aria-label="clear-button" onClick={handleClear}>
|
||||||
|
<ClearIcon />
|
||||||
|
</IconButton>
|
||||||
|
<InputBase
|
||||||
|
autoFocus
|
||||||
|
sx={{ ml: 1, flex: 1, backgroundColor: "#fff", p: 1 }}
|
||||||
|
placeholder={placeholder}
|
||||||
|
inputProps={{ "aria-label": "search-input" }}
|
||||||
|
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>
|
||||||
|
</Paper>
|
||||||
|
);
|
||||||
|
}
|
7
createEmotionCache.ts
Normal file
7
createEmotionCache.ts
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
import createCache from "@emotion/cache";
|
||||||
|
|
||||||
|
const createEmotionCache = () => {
|
||||||
|
return createCache({ key: "css", prepend: true });
|
||||||
|
};
|
||||||
|
|
||||||
|
export default createEmotionCache;
|
286
flake.lock
Normal file
286
flake.lock
Normal file
@ -0,0 +1,286 @@
|
|||||||
|
{
|
||||||
|
"nodes": {
|
||||||
|
"alejandra": {
|
||||||
|
"inputs": {
|
||||||
|
"fenix": "fenix",
|
||||||
|
"flakeCompat": "flakeCompat",
|
||||||
|
"nixpkgs": [
|
||||||
|
"dream2nix",
|
||||||
|
"nixpkgs"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1658427149,
|
||||||
|
"narHash": "sha256-ToD/1z/q5VHsLMrS2h96vjJoLho59eNRtknOUd19ey8=",
|
||||||
|
"owner": "kamadorueda",
|
||||||
|
"repo": "alejandra",
|
||||||
|
"rev": "f5a22afd2adfb249b4e68e0b33aa1f0fb73fb1be",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "kamadorueda",
|
||||||
|
"repo": "alejandra",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"all-cabal-json": {
|
||||||
|
"flake": false,
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1665552503,
|
||||||
|
"narHash": "sha256-r14RmRSwzv5c+bWKUDaze6pXM7nOsiz1H8nvFHJvufc=",
|
||||||
|
"owner": "nix-community",
|
||||||
|
"repo": "all-cabal-json",
|
||||||
|
"rev": "d7c0434eebffb305071404edcf9d5cd99703878e",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nix-community",
|
||||||
|
"ref": "hackage",
|
||||||
|
"repo": "all-cabal-json",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"crane": {
|
||||||
|
"flake": false,
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1661875961,
|
||||||
|
"narHash": "sha256-f1h/2c6Teeu1ofAHWzrS8TwBPcnN+EEu+z1sRVmMQTk=",
|
||||||
|
"owner": "ipetkov",
|
||||||
|
"repo": "crane",
|
||||||
|
"rev": "d9f394e4e20e97c2a60c3ad82c2b6ef99be19e24",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "ipetkov",
|
||||||
|
"repo": "crane",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"devshell": {
|
||||||
|
"flake": false,
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1663445644,
|
||||||
|
"narHash": "sha256-+xVlcK60x7VY1vRJbNUEAHi17ZuoQxAIH4S4iUFUGBA=",
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "devshell",
|
||||||
|
"rev": "e3dc3e21594fe07bdb24bdf1c8657acaa4cb8f66",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "devshell",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"dream2nix": {
|
||||||
|
"inputs": {
|
||||||
|
"alejandra": "alejandra",
|
||||||
|
"all-cabal-json": "all-cabal-json",
|
||||||
|
"crane": "crane",
|
||||||
|
"devshell": "devshell",
|
||||||
|
"flake-utils-pre-commit": "flake-utils-pre-commit",
|
||||||
|
"ghc-utils": "ghc-utils",
|
||||||
|
"gomod2nix": "gomod2nix",
|
||||||
|
"mach-nix": "mach-nix",
|
||||||
|
"nixpkgs": "nixpkgs",
|
||||||
|
"poetry2nix": "poetry2nix",
|
||||||
|
"pre-commit-hooks": "pre-commit-hooks"
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1667429039,
|
||||||
|
"narHash": "sha256-Lu6da25JioHzerkLHAHSO9suCQFzJ/XBjkcGCIbasLM=",
|
||||||
|
"owner": "nix-community",
|
||||||
|
"repo": "dream2nix",
|
||||||
|
"rev": "5252794e58eedb02d607fa3187ffead7becc81b0",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nix-community",
|
||||||
|
"repo": "dream2nix",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"fenix": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs": [
|
||||||
|
"dream2nix",
|
||||||
|
"alejandra",
|
||||||
|
"nixpkgs"
|
||||||
|
],
|
||||||
|
"rust-analyzer-src": "rust-analyzer-src"
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1657607339,
|
||||||
|
"narHash": "sha256-HaqoAwlbVVZH2n4P3jN2FFPMpVuhxDy1poNOR7kzODc=",
|
||||||
|
"owner": "nix-community",
|
||||||
|
"repo": "fenix",
|
||||||
|
"rev": "b814c83d9e6aa5a28d0cf356ecfdafb2505ad37d",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nix-community",
|
||||||
|
"repo": "fenix",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"flake-utils-pre-commit": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1644229661,
|
||||||
|
"narHash": "sha256-1YdnJAsNy69bpcjuoKdOYQX0YxZBiCYZo4Twxerqv7k=",
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "flake-utils",
|
||||||
|
"rev": "3cecb5b042f7f209c56ffd8371b2711a290ec797",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "flake-utils",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"flakeCompat": {
|
||||||
|
"flake": false,
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1650374568,
|
||||||
|
"narHash": "sha256-Z+s0J8/r907g149rllvwhb4pKi8Wam5ij0st8PwAh+E=",
|
||||||
|
"owner": "edolstra",
|
||||||
|
"repo": "flake-compat",
|
||||||
|
"rev": "b4a34015c698c7793d592d66adbab377907a2be8",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "edolstra",
|
||||||
|
"repo": "flake-compat",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ghc-utils": {
|
||||||
|
"flake": false,
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1662774800,
|
||||||
|
"narHash": "sha256-1Rd2eohGUw/s1tfvkepeYpg8kCEXiIot0RijapUjAkE=",
|
||||||
|
"ref": "refs/heads/master",
|
||||||
|
"rev": "bb3a2d3dc52ff0253fb9c2812bd7aa2da03e0fea",
|
||||||
|
"revCount": 1072,
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://gitlab.haskell.org/bgamari/ghc-utils"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://gitlab.haskell.org/bgamari/ghc-utils"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"gomod2nix": {
|
||||||
|
"flake": false,
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1627572165,
|
||||||
|
"narHash": "sha256-MFpwnkvQpauj799b4QTBJQFEddbD02+Ln5k92QyHOSk=",
|
||||||
|
"owner": "tweag",
|
||||||
|
"repo": "gomod2nix",
|
||||||
|
"rev": "67f22dd738d092c6ba88e420350ada0ed4992ae8",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "tweag",
|
||||||
|
"repo": "gomod2nix",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"mach-nix": {
|
||||||
|
"flake": false,
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1634711045,
|
||||||
|
"narHash": "sha256-m5A2Ty88NChLyFhXucECj6+AuiMZPHXNbw+9Kcs7F6Y=",
|
||||||
|
"owner": "DavHau",
|
||||||
|
"repo": "mach-nix",
|
||||||
|
"rev": "4433f74a97b94b596fa6cd9b9c0402104aceef5d",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"id": "mach-nix",
|
||||||
|
"type": "indirect"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nixpkgs": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1665580254,
|
||||||
|
"narHash": "sha256-hO61XPkp1Hphl4HGNzj1VvDH5URt7LI6LaY/385Eul4=",
|
||||||
|
"owner": "NixOS",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "f634d427b0224a5f531ea5aa10c3960ba6ec5f0f",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"id": "nixpkgs",
|
||||||
|
"ref": "nixos-unstable",
|
||||||
|
"type": "indirect"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"poetry2nix": {
|
||||||
|
"flake": false,
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1632969109,
|
||||||
|
"narHash": "sha256-jPDclkkiAy5m2gGLBlKgH+lQtbF7tL4XxBrbSzw+Ioc=",
|
||||||
|
"owner": "nix-community",
|
||||||
|
"repo": "poetry2nix",
|
||||||
|
"rev": "aee8f04296c39d88155e05d25cfc59dfdd41cc77",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nix-community",
|
||||||
|
"ref": "1.21.0",
|
||||||
|
"repo": "poetry2nix",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"pre-commit-hooks": {
|
||||||
|
"inputs": {
|
||||||
|
"flake-utils": [
|
||||||
|
"dream2nix",
|
||||||
|
"flake-utils-pre-commit"
|
||||||
|
],
|
||||||
|
"nixpkgs": [
|
||||||
|
"dream2nix",
|
||||||
|
"nixpkgs"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1646153636,
|
||||||
|
"narHash": "sha256-AlWHMzK+xJ1mG267FdT8dCq/HvLCA6jwmx2ZUy5O8tY=",
|
||||||
|
"owner": "cachix",
|
||||||
|
"repo": "pre-commit-hooks.nix",
|
||||||
|
"rev": "b6bc0b21e1617e2b07d8205e7fae7224036dfa4b",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "cachix",
|
||||||
|
"repo": "pre-commit-hooks.nix",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": {
|
||||||
|
"inputs": {
|
||||||
|
"dream2nix": "dream2nix"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"rust-analyzer-src": {
|
||||||
|
"flake": false,
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1657557289,
|
||||||
|
"narHash": "sha256-PRW+nUwuqNTRAEa83SfX+7g+g8nQ+2MMbasQ9nt6+UM=",
|
||||||
|
"owner": "rust-lang",
|
||||||
|
"repo": "rust-analyzer",
|
||||||
|
"rev": "caf23f29144b371035b864a1017dbc32573ad56d",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "rust-lang",
|
||||||
|
"ref": "nightly",
|
||||||
|
"repo": "rust-analyzer",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": "root",
|
||||||
|
"version": 7
|
||||||
|
}
|
30
flake.nix
Normal file
30
flake.nix
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
{
|
||||||
|
inputs.dream2nix.url = "github:nix-community/dream2nix";
|
||||||
|
outputs = inp:
|
||||||
|
let
|
||||||
|
inherit (builtins.fromJSON (builtins.readFile ./package.json)) name;
|
||||||
|
in
|
||||||
|
inp.dream2nix.lib.makeFlakeOutputs {
|
||||||
|
systemsFromFile = ./nix_systems;
|
||||||
|
config.projectRoot = ./.;
|
||||||
|
source = ./.;
|
||||||
|
settings = [
|
||||||
|
{
|
||||||
|
subsystemInfo.nodejs = 18;
|
||||||
|
}
|
||||||
|
];
|
||||||
|
packageOverrides = {
|
||||||
|
${name}.staticPage = {
|
||||||
|
installPhase = ''
|
||||||
|
runHook preInstall
|
||||||
|
|
||||||
|
npm run export
|
||||||
|
mkdir -p $out/static
|
||||||
|
cp -r ./out/* $out/static/
|
||||||
|
|
||||||
|
runHook postInstall
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
10
next.config.js
Normal file
10
next.config.js
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
/** @type {import('next').NextConfig} */
|
||||||
|
const nextConfig = {
|
||||||
|
reactStrictMode: true,
|
||||||
|
swcMinify: true,
|
||||||
|
images: {
|
||||||
|
loader: "custom",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = nextConfig;
|
1
nix_systems
Normal file
1
nix_systems
Normal file
@ -0,0 +1 @@
|
|||||||
|
x86_64-linux
|
6059
package-lock.json
generated
Normal file
6059
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
28
package.json
Normal file
28
package.json
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
{
|
||||||
|
"name": "nextapp",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"private": true,
|
||||||
|
"scripts": {
|
||||||
|
"dev": "next dev",
|
||||||
|
"build": "next build",
|
||||||
|
"export": "next export",
|
||||||
|
"start": "next start",
|
||||||
|
"lint": "next lint"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@emotion/react": "^11.10.5",
|
||||||
|
"@emotion/styled": "^11.10.5",
|
||||||
|
"@fontsource/roboto": "^4.5.8",
|
||||||
|
"@mui/icons-material": "^5.10.9",
|
||||||
|
"@mui/material": "^5.10.13",
|
||||||
|
"@types/node": "18.11.9",
|
||||||
|
"@types/react": "^18.0.25",
|
||||||
|
"@types/react-dom": "18.0.8",
|
||||||
|
"eslint": "8.27.0",
|
||||||
|
"eslint-config-next": "13.0.2",
|
||||||
|
"next": "13.0.2",
|
||||||
|
"react": "18.2.0",
|
||||||
|
"react-dom": "18.2.0",
|
||||||
|
"typescript": "4.8.4"
|
||||||
|
}
|
||||||
|
}
|
56
pages/_app.tsx
Normal file
56
pages/_app.tsx
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
import * as React from "react";
|
||||||
|
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 "@fontsource/roboto/300.css";
|
||||||
|
import "@fontsource/roboto/400.css";
|
||||||
|
import "@fontsource/roboto/500.css";
|
||||||
|
import "@fontsource/roboto/700.css";
|
||||||
|
|
||||||
|
import createEmotionCache from "../createEmotionCache";
|
||||||
|
import { lightThemeOptions, darkThemeOptions } from "../styles/theme";
|
||||||
|
import "../styles/globals.css";
|
||||||
|
import { Layout } from "../components/layout";
|
||||||
|
import Head from "next/head";
|
||||||
|
|
||||||
|
interface MyAppProps extends AppProps {
|
||||||
|
emotionCache?: EmotionCache;
|
||||||
|
}
|
||||||
|
|
||||||
|
const clientSideEmotionCache = createEmotionCache();
|
||||||
|
|
||||||
|
const lightTheme = createTheme(lightThemeOptions);
|
||||||
|
const darkTheme = createTheme(darkThemeOptions);
|
||||||
|
|
||||||
|
const MyApp: React.FunctionComponent<MyAppProps> = (props) => {
|
||||||
|
const { Component, emotionCache = clientSideEmotionCache, pageProps } = props;
|
||||||
|
const userPrefersDarkmode = useMediaQuery("(prefers-color-scheme: dark)");
|
||||||
|
|
||||||
|
const getContent = () => {
|
||||||
|
return (
|
||||||
|
<Layout>
|
||||||
|
<Component {...pageProps} />
|
||||||
|
</Layout>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Head>
|
||||||
|
<title>noogle</title>
|
||||||
|
<meta name="description" content="Search nix functions" />
|
||||||
|
<link rel="icon" href="/favicon.png" />
|
||||||
|
</Head>
|
||||||
|
|
||||||
|
<CacheProvider value={emotionCache}>
|
||||||
|
<ThemeProvider theme={userPrefersDarkmode ? darkTheme : lightTheme}>
|
||||||
|
<CssBaseline />
|
||||||
|
{getContent()}
|
||||||
|
</ThemeProvider>
|
||||||
|
</CacheProvider>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default MyApp;
|
450
pages/index.tsx
Normal file
450
pages/index.tsx
Normal file
@ -0,0 +1,450 @@
|
|||||||
|
import { BasicList, BasicListItem } from "../components/basicList";
|
||||||
|
import { useState, useMemo } from "react";
|
||||||
|
import { Box } from "@mui/material";
|
||||||
|
import FunctionItem from "../components/functionItem/functionItem";
|
||||||
|
import { NixType } from "../types/basicDataView";
|
||||||
|
import { Preview } from "../components/preview/preview";
|
||||||
|
|
||||||
|
const libfuns = {
|
||||||
|
mapAttrs: {
|
||||||
|
"attr-path": "builtins.mapAttrs",
|
||||||
|
"doc-url":
|
||||||
|
"https://nixos.org/manual/nix/stable/language/builtins.html#builtins-mapAttrs",
|
||||||
|
source: "builtin",
|
||||||
|
from: "attrset",
|
||||||
|
to: "attrset",
|
||||||
|
},
|
||||||
|
"mapAttrs'": {
|
||||||
|
"attr-path": "lib.mapAttrs'",
|
||||||
|
"doc-url":
|
||||||
|
"https://nixos.org/manual/nixpkgs/stable/#sec-functions-library-attrset",
|
||||||
|
source: "nixpkgs",
|
||||||
|
from: "attrset",
|
||||||
|
to: "attrset",
|
||||||
|
},
|
||||||
|
toString: {
|
||||||
|
"attr-path": "builtins.toString'",
|
||||||
|
"doc-url":
|
||||||
|
"https://nixos.org/manual/nix/stable/language/builtins.html#builtins-toString",
|
||||||
|
source: "builtin",
|
||||||
|
from: "any",
|
||||||
|
to: "string",
|
||||||
|
},
|
||||||
|
genAttrs: {
|
||||||
|
"attr-path": "lib.genAttrs",
|
||||||
|
"doc-url":
|
||||||
|
"https://nixos.org/manual/nixpkgs/stable/#sec-functions-library-attrset",
|
||||||
|
source: "nixpkgs",
|
||||||
|
from: "list",
|
||||||
|
to: "attrset",
|
||||||
|
},
|
||||||
|
|
||||||
|
forEach: {
|
||||||
|
"attr-path": "lib.forEach",
|
||||||
|
"doc-url":
|
||||||
|
"https://nixos.org/manual/nixpkgs/stable/#sec-functions-library-lists",
|
||||||
|
source: "nixpkgs",
|
||||||
|
from: "list",
|
||||||
|
to: "list",
|
||||||
|
},
|
||||||
|
foldr: {
|
||||||
|
"attr-path": "lib.foldr",
|
||||||
|
"doc-url":
|
||||||
|
"https://nixos.org/manual/nixpkgs/stable/#sec-functions-library-lists",
|
||||||
|
source: "nixpkgs",
|
||||||
|
from: "list",
|
||||||
|
to: "any",
|
||||||
|
},
|
||||||
|
foldl: {
|
||||||
|
"attr-path": "lib.foldl",
|
||||||
|
"doc-url":
|
||||||
|
"https://nixos.org/manual/nixpkgs/stable/#sec-functions-library-lists",
|
||||||
|
source: "nixpkgs",
|
||||||
|
from: "list",
|
||||||
|
to: "any",
|
||||||
|
},
|
||||||
|
"foldl'": {
|
||||||
|
"attr-path": "lib.foldl'",
|
||||||
|
"doc-url":
|
||||||
|
"https://nixos.org/manual/nixpkgs/stable/#sec-functions-library-lists",
|
||||||
|
source: "nixpkgs",
|
||||||
|
from: "list",
|
||||||
|
to: "any",
|
||||||
|
},
|
||||||
|
imap0: {
|
||||||
|
"attr-path": "lib.imap0",
|
||||||
|
"doc-url":
|
||||||
|
"https://nixos.org/manual/nixpkgs/stable/#sec-functions-library-lists",
|
||||||
|
source: "nixpkgs",
|
||||||
|
from: "list",
|
||||||
|
to: "list",
|
||||||
|
},
|
||||||
|
imap1: {
|
||||||
|
"attr-path": "lib.imap1",
|
||||||
|
"doc-url":
|
||||||
|
"https://nixos.org/manual/nixpkgs/stable/#sec-functions-library-lists",
|
||||||
|
source: "nixpkgs",
|
||||||
|
from: "list",
|
||||||
|
to: "list",
|
||||||
|
},
|
||||||
|
concatMap: {
|
||||||
|
"attr-path": "lib.concatMap",
|
||||||
|
"doc-url":
|
||||||
|
"https://nixos.org/manual/nixpkgs/stable/#sec-functions-library-lists",
|
||||||
|
source: "nixpkgs",
|
||||||
|
from: "list",
|
||||||
|
to: "list",
|
||||||
|
},
|
||||||
|
flatten: {
|
||||||
|
"attr-path": "lib.flatten",
|
||||||
|
"doc-url":
|
||||||
|
"https://nixos.org/manual/nixpkgs/stable/#sec-functions-library-lists",
|
||||||
|
source: "nixpkgs",
|
||||||
|
from: "list",
|
||||||
|
to: "list",
|
||||||
|
},
|
||||||
|
remove: {
|
||||||
|
"attr-path": "lib.remove",
|
||||||
|
"doc-url":
|
||||||
|
"https://nixos.org/manual/nixpkgs/stable/#sec-functions-library-lists",
|
||||||
|
source: "nixpkgs",
|
||||||
|
from: "list",
|
||||||
|
to: "list",
|
||||||
|
},
|
||||||
|
findSingle: {
|
||||||
|
"attr-path": "lib.findSingle",
|
||||||
|
"doc-url":
|
||||||
|
"https://nixos.org/manual/nixpkgs/stable/#sec-functions-library-lists",
|
||||||
|
source: "nixpkgs",
|
||||||
|
from: "list",
|
||||||
|
to: "any",
|
||||||
|
},
|
||||||
|
findFirst: {
|
||||||
|
"attr-path": "lib.findFirst",
|
||||||
|
"doc-url":
|
||||||
|
"https://nixos.org/manual/nixpkgs/stable/#sec-functions-library-lists",
|
||||||
|
source: "nixpkgs",
|
||||||
|
from: "list",
|
||||||
|
to: "any",
|
||||||
|
},
|
||||||
|
any: {
|
||||||
|
"attr-path": "lib.any",
|
||||||
|
"doc-url":
|
||||||
|
"https://nixos.org/manual/nixpkgs/stable/#sec-functions-library-lists",
|
||||||
|
source: "nixpkgs",
|
||||||
|
from: "list",
|
||||||
|
to: "true",
|
||||||
|
},
|
||||||
|
all: {
|
||||||
|
"attr-path": "lib.all",
|
||||||
|
"doc-url":
|
||||||
|
"https://nixos.org/manual/nixpkgs/stable/#sec-functions-library-lists",
|
||||||
|
source: "nixpkgs",
|
||||||
|
from: "list",
|
||||||
|
to: "true",
|
||||||
|
},
|
||||||
|
count: {
|
||||||
|
"attr-path": "lib.count",
|
||||||
|
"doc-url":
|
||||||
|
"https://nixos.org/manual/nixpkgs/stable/#sec-functions-library-lists",
|
||||||
|
source: "nixpkgs",
|
||||||
|
from: "list",
|
||||||
|
to: "int",
|
||||||
|
},
|
||||||
|
optional: {
|
||||||
|
"attr-path": "lib.optional",
|
||||||
|
"doc-url":
|
||||||
|
"https://nixos.org/manual/nixpkgs/stable/#sec-functions-library-lists",
|
||||||
|
source: "nixpkgs",
|
||||||
|
from: "bool",
|
||||||
|
to: "list",
|
||||||
|
},
|
||||||
|
optionals: {
|
||||||
|
"attr-path": "lib.optionals",
|
||||||
|
"doc-url":
|
||||||
|
"https://nixos.org/manual/nixpkgs/stable/#sec-functions-library-lists",
|
||||||
|
source: "nixpkgs",
|
||||||
|
from: "bool",
|
||||||
|
to: "list",
|
||||||
|
},
|
||||||
|
toList: {
|
||||||
|
"attr-path": "lib.toList",
|
||||||
|
"doc-url":
|
||||||
|
"https://nixos.org/manual/nixpkgs/stable/#sec-functions-library-lists",
|
||||||
|
source: "nixpkgs",
|
||||||
|
from: "any",
|
||||||
|
to: "list",
|
||||||
|
},
|
||||||
|
range: {
|
||||||
|
"attr-path": "lib.range",
|
||||||
|
"doc-url":
|
||||||
|
"https://nixos.org/manual/nixpkgs/stable/#sec-functions-library-lists",
|
||||||
|
source: "nixpkgs",
|
||||||
|
from: "int",
|
||||||
|
to: "list",
|
||||||
|
},
|
||||||
|
partition: {
|
||||||
|
"attr-path": "lib.partition",
|
||||||
|
"doc-url":
|
||||||
|
"https://nixos.org/manual/nixpkgs/stable/#sec-functions-library-lists",
|
||||||
|
source: "nixpkgs",
|
||||||
|
from: "list",
|
||||||
|
to: "list",
|
||||||
|
},
|
||||||
|
"groupBy'": {
|
||||||
|
"attr-path": "lib.groupBy'",
|
||||||
|
"doc-url":
|
||||||
|
"https://nixos.org/manual/nixpkgs/stable/#sec-functions-library-lists",
|
||||||
|
source: "nixpkgs",
|
||||||
|
from: "list",
|
||||||
|
to: "list",
|
||||||
|
},
|
||||||
|
groupBy: {
|
||||||
|
"attr-path": "lib.groupBy",
|
||||||
|
"doc-url":
|
||||||
|
"https://nixos.org/manual/nixpkgs/stable/#sec-functions-library-lists",
|
||||||
|
source: "nixpkgs",
|
||||||
|
from: "list",
|
||||||
|
to: "list",
|
||||||
|
},
|
||||||
|
zipListsWith: {
|
||||||
|
"attr-path": "lib.zipListsWith",
|
||||||
|
"doc-url":
|
||||||
|
"https://nixos.org/manual/nixpkgs/stable/#sec-functions-library-lists",
|
||||||
|
source: "nixpkgs",
|
||||||
|
from: "list",
|
||||||
|
to: "list",
|
||||||
|
},
|
||||||
|
zipLists: {
|
||||||
|
"attr-path": "lib.zipLists",
|
||||||
|
"doc-url":
|
||||||
|
"https://nixos.org/manual/nixpkgs/stable/#sec-functions-library-lists",
|
||||||
|
source: "nixpkgs",
|
||||||
|
from: "list",
|
||||||
|
to: "list",
|
||||||
|
},
|
||||||
|
reverseList: {
|
||||||
|
"attr-path": "lib.reverseList",
|
||||||
|
"doc-url":
|
||||||
|
"https://nixos.org/manual/nixpkgs/stable/#sec-functions-library-lists",
|
||||||
|
source: "nixpkgs",
|
||||||
|
from: "list",
|
||||||
|
to: "list",
|
||||||
|
},
|
||||||
|
listDfs: {
|
||||||
|
"attr-path": "lib.listDfs",
|
||||||
|
"doc-url":
|
||||||
|
"https://nixos.org/manual/nixpkgs/stable/#sec-functions-library-lists",
|
||||||
|
source: "nixpkgs",
|
||||||
|
from: "list",
|
||||||
|
to: "attrset",
|
||||||
|
},
|
||||||
|
toposort: {
|
||||||
|
"attr-path": "lib.toposort",
|
||||||
|
"doc-url":
|
||||||
|
"https://nixos.org/manual/nixpkgs/stable/#sec-functions-library-lists",
|
||||||
|
source: "nixpkgs",
|
||||||
|
from: "list",
|
||||||
|
to: "list",
|
||||||
|
},
|
||||||
|
sort: {
|
||||||
|
"attr-path": "lib.sort",
|
||||||
|
"doc-url":
|
||||||
|
"https://nixos.org/manual/nixpkgs/stable/#sec-functions-library-lists",
|
||||||
|
source: "nixpkgs",
|
||||||
|
from: "list",
|
||||||
|
to: "list",
|
||||||
|
},
|
||||||
|
compareLists: {
|
||||||
|
"attr-path": "lib.compareLists",
|
||||||
|
"doc-url":
|
||||||
|
"https://nixos.org/manual/nixpkgs/stable/#sec-functions-library-lists",
|
||||||
|
source: "nixpkgs",
|
||||||
|
from: "list",
|
||||||
|
to: "int",
|
||||||
|
},
|
||||||
|
naturalSort: {
|
||||||
|
"attr-path": "lib.naturalSort",
|
||||||
|
"doc-url":
|
||||||
|
"https://nixos.org/manual/nixpkgs/stable/#sec-functions-library-lists",
|
||||||
|
source: "nixpkgs",
|
||||||
|
from: "list",
|
||||||
|
to: "list",
|
||||||
|
},
|
||||||
|
take: {
|
||||||
|
"attr-path": "lib.take",
|
||||||
|
"doc-url":
|
||||||
|
"https://nixos.org/manual/nixpkgs/stable/#sec-functions-library-lists",
|
||||||
|
source: "nixpkgs",
|
||||||
|
from: "list",
|
||||||
|
to: "list",
|
||||||
|
},
|
||||||
|
sublist: {
|
||||||
|
"attr-path": "lib.sublist",
|
||||||
|
"doc-url":
|
||||||
|
"https://nixos.org/manual/nixpkgs/stable/#sec-functions-library-lists",
|
||||||
|
source: "nixpkgs",
|
||||||
|
from: "list",
|
||||||
|
to: "list",
|
||||||
|
},
|
||||||
|
last: {
|
||||||
|
"attr-path": "lib.last",
|
||||||
|
"doc-url":
|
||||||
|
"https://nixos.org/manual/nixpkgs/stable/#sec-functions-library-lists",
|
||||||
|
source: "nixpkgs",
|
||||||
|
from: "list",
|
||||||
|
to: "any",
|
||||||
|
},
|
||||||
|
init: {
|
||||||
|
"attr-path": "lib.init",
|
||||||
|
"doc-url":
|
||||||
|
"https://nixos.org/manual/nixpkgs/stable/#sec-functions-library-lists",
|
||||||
|
source: "nixpkgs",
|
||||||
|
from: "list",
|
||||||
|
to: "list",
|
||||||
|
},
|
||||||
|
crossLists: {
|
||||||
|
"attr-path": "lib.crossLists",
|
||||||
|
"doc-url":
|
||||||
|
"https://nixos.org/manual/nixpkgs/stable/#sec-functions-library-lists",
|
||||||
|
source: "nixpkgs",
|
||||||
|
from: "list",
|
||||||
|
to: "list",
|
||||||
|
},
|
||||||
|
unique: {
|
||||||
|
"attr-path": "lib.unique",
|
||||||
|
"doc-url":
|
||||||
|
"https://nixos.org/manual/nixpkgs/stable/#sec-functions-library-lists",
|
||||||
|
source: "nixpkgs",
|
||||||
|
from: "list",
|
||||||
|
to: "list",
|
||||||
|
},
|
||||||
|
intersectLists: {
|
||||||
|
"attr-path": "lib.intersectLists",
|
||||||
|
"doc-url":
|
||||||
|
"https://nixos.org/manual/nixpkgs/stable/#sec-functions-library-lists",
|
||||||
|
source: "nixpkgs",
|
||||||
|
from: "list",
|
||||||
|
to: "list",
|
||||||
|
},
|
||||||
|
subtractLists: {
|
||||||
|
"attr-path": "lib.subtractLists",
|
||||||
|
"doc-url":
|
||||||
|
"https://nixos.org/manual/nixpkgs/stable/#sec-functions-library-lists",
|
||||||
|
source: "nixpkgs",
|
||||||
|
from: "list",
|
||||||
|
to: "list",
|
||||||
|
},
|
||||||
|
mutuallyExclusive: {
|
||||||
|
"attr-path": "lib.mutuallyExclusive",
|
||||||
|
"doc-url":
|
||||||
|
"https://nixos.org/manual/nixpkgs/stable/#sec-functions-library-lists",
|
||||||
|
source: "nixpkgs",
|
||||||
|
from: "list",
|
||||||
|
to: "bool",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export type FuncData = {
|
||||||
|
name: string;
|
||||||
|
info: {
|
||||||
|
"attr-path": string;
|
||||||
|
"doc-url": string;
|
||||||
|
source: string;
|
||||||
|
from: string;
|
||||||
|
to: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const mockData: FuncData[] = Object.entries(libfuns).map(([key, value]) => ({
|
||||||
|
name: key,
|
||||||
|
info: value,
|
||||||
|
}));
|
||||||
|
|
||||||
|
const pipe =
|
||||||
|
(...fns: ((arr: FuncData[]) => FuncData[])[]) =>
|
||||||
|
(x: FuncData[]) =>
|
||||||
|
fns.reduce((v, f) => f(v), x);
|
||||||
|
|
||||||
|
const search =
|
||||||
|
(term: string) =>
|
||||||
|
(data: FuncData[]): FuncData[] => {
|
||||||
|
return data.filter((item) => {
|
||||||
|
return Object.values(item).some((value) => {
|
||||||
|
const valueAsString = value.toString();
|
||||||
|
return valueAsString.toLowerCase().includes(term.toLocaleLowerCase());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
const filter =
|
||||||
|
(to: NixType, from: NixType) =>
|
||||||
|
(data: FuncData[]): FuncData[] => {
|
||||||
|
return data.filter(({ info }) => info.from === from && info.to === to);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function FunctionsPage() {
|
||||||
|
// const [visibleFuncs, setVisibleFuncs] = useState(mockData);
|
||||||
|
const [selected, setSelected] = useState<string | null>(null);
|
||||||
|
const [term, setTerm] = useState<string>("");
|
||||||
|
const [to, setTo] = useState<NixType>("any");
|
||||||
|
const [from, setFrom] = useState<NixType>("any");
|
||||||
|
|
||||||
|
const handleSelect = (key: string) => {
|
||||||
|
setSelected((curr) => {
|
||||||
|
if (curr === key) {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const filteredData = useMemo(
|
||||||
|
() => pipe(filter(to, from), search(term))(mockData),
|
||||||
|
[to, from, term]
|
||||||
|
);
|
||||||
|
|
||||||
|
const handleSearch = (term: string) => {
|
||||||
|
setTerm(term);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleFilter = (t: NixType, mode: "to" | "from") => {
|
||||||
|
if (mode === "from") {
|
||||||
|
setFrom(t);
|
||||||
|
}
|
||||||
|
if (mode === "to") {
|
||||||
|
setTo(t);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const preRenderedItems: BasicListItem[] = filteredData.map(
|
||||||
|
({ name, info }) => ({
|
||||||
|
item: (
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
width: "100%",
|
||||||
|
height: "100%",
|
||||||
|
}}
|
||||||
|
onClick={() => handleSelect(name)}
|
||||||
|
>
|
||||||
|
<FunctionItem name={name} info={info} selected={selected === name} />
|
||||||
|
</Box>
|
||||||
|
),
|
||||||
|
key: name,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
const preview = (
|
||||||
|
<Preview func={mockData.find((f) => f.name === selected) || mockData[0]} />
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box sx={{ ml: 2 }}>
|
||||||
|
<BasicList
|
||||||
|
items={preRenderedItems}
|
||||||
|
handleSearch={handleSearch}
|
||||||
|
handleFilter={handleFilter}
|
||||||
|
preview={selected ? preview : null}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
}
|
BIN
public/favicon.ico
Normal file
BIN
public/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 25 KiB |
BIN
public/favicon.png
Normal file
BIN
public/favicon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.2 KiB |
4
public/vercel.svg
Normal file
4
public/vercel.svg
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
<svg width="283" height="64" viewBox="0 0 283 64" fill="none"
|
||||||
|
xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M141.04 16c-11.04 0-19 7.2-19 18s8.96 18 20 18c6.67 0 12.55-2.64 16.19-7.09l-7.65-4.42c-2.02 2.21-5.09 3.5-8.54 3.5-4.79 0-8.86-2.5-10.37-6.5h28.02c.22-1.12.35-2.28.35-3.5 0-10.79-7.96-17.99-19-17.99zm-9.46 14.5c1.25-3.99 4.67-6.5 9.45-6.5 4.79 0 8.21 2.51 9.45 6.5h-18.9zM248.72 16c-11.04 0-19 7.2-19 18s8.96 18 20 18c6.67 0 12.55-2.64 16.19-7.09l-7.65-4.42c-2.02 2.21-5.09 3.5-8.54 3.5-4.79 0-8.86-2.5-10.37-6.5h28.02c.22-1.12.35-2.28.35-3.5 0-10.79-7.96-17.99-19-17.99zm-9.45 14.5c1.25-3.99 4.67-6.5 9.45-6.5 4.79 0 8.21 2.51 9.45 6.5h-18.9zM200.24 34c0 6 3.92 10 10 10 4.12 0 7.21-1.87 8.8-4.92l7.68 4.43c-3.18 5.3-9.14 8.49-16.48 8.49-11.05 0-19-7.2-19-18s7.96-18 19-18c7.34 0 13.29 3.19 16.48 8.49l-7.68 4.43c-1.59-3.05-4.68-4.92-8.8-4.92-6.07 0-10 4-10 10zm82.48-29v46h-9V5h9zM36.95 0L73.9 64H0L36.95 0zm92.38 5l-27.71 48L73.91 5H84.3l17.32 30 17.32-30h10.39zm58.91 12v9.69c-1-.29-2.06-.49-3.2-.49-5.81 0-10 4-10 10V51h-9V17h9v9.2c0-5.08 5.91-9.2 13.2-9.2z" fill="#000"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.1 KiB |
21
styles/globals.css
Normal file
21
styles/globals.css
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
html,
|
||||||
|
body {
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
background-color: rgb(242, 248, 253);
|
||||||
|
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
|
||||||
|
Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: inherit;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
* {
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.react-terminal-wrapper:before {
|
||||||
|
background: unset !important;
|
||||||
|
}
|
16
styles/theme/darkThemeOptions.ts
Normal file
16
styles/theme/darkThemeOptions.ts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import { ThemeOptions } from "@mui/material/styles";
|
||||||
|
|
||||||
|
const darkThemeOptions: ThemeOptions = {
|
||||||
|
palette: {
|
||||||
|
mode: "dark",
|
||||||
|
primary: {
|
||||||
|
main: "#6586c8"
|
||||||
|
|
||||||
|
},
|
||||||
|
secondary: {
|
||||||
|
main: "#6ad541"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export { darkThemeOptions };
|
2
styles/theme/index.tsx
Normal file
2
styles/theme/index.tsx
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
export { lightThemeOptions } from "./lightThemeOptions";
|
||||||
|
export { darkThemeOptions } from "./darkThemeOptions";
|
16
styles/theme/lightThemeOptions.ts
Normal file
16
styles/theme/lightThemeOptions.ts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import { ThemeOptions } from "@mui/material/styles";
|
||||||
|
|
||||||
|
const lightThemeOptions: ThemeOptions = {
|
||||||
|
palette: {
|
||||||
|
mode: "light",
|
||||||
|
primary: {
|
||||||
|
main: "#6586c8"
|
||||||
|
|
||||||
|
},
|
||||||
|
secondary: {
|
||||||
|
main: "#6ad541"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export { lightThemeOptions };
|
20
tsconfig.json
Normal file
20
tsconfig.json
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "es5",
|
||||||
|
"lib": ["dom", "dom.iterable", "esnext"],
|
||||||
|
"allowJs": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"strict": true,
|
||||||
|
"forceConsistentCasingInFileNames": true,
|
||||||
|
"noEmit": true,
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"module": "esnext",
|
||||||
|
"moduleResolution": "node",
|
||||||
|
"resolveJsonModule": true,
|
||||||
|
"isolatedModules": true,
|
||||||
|
"jsx": "preserve",
|
||||||
|
"incremental": true
|
||||||
|
},
|
||||||
|
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
|
||||||
|
"exclude": ["node_modules"]
|
||||||
|
}
|
12
types/basicDataView.ts
Normal file
12
types/basicDataView.ts
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
export type BasicDataItem = {
|
||||||
|
item: React.ReactNode;
|
||||||
|
key: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type BasicDataViewProps = {
|
||||||
|
items: BasicDataItem[];
|
||||||
|
pageCount?: number;
|
||||||
|
handleSearch?: (term: string) => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type NixType = "attrset" | "list" | "string" | "int" | "bool" | "any";
|
Loading…
Reference in New Issue
Block a user