Added some initial styles, dependencies, next-auth, and page structure

This commit is contained in:
Valtteri Karesto
2021-11-11 11:42:36 +02:00
parent 583371489c
commit e7efed79ce
24 changed files with 6224 additions and 86 deletions

3
.env.example Normal file
View File

@@ -0,0 +1,3 @@
NEXTAUTH_URL=https://example.com
GITHUB_SECRET=""
GITHUB_ID=""

155
components/DropdownMenu.tsx Normal file
View File

@@ -0,0 +1,155 @@
/** @jsxImportSource theme-ui */
import * as DropdownMenu from "@radix-ui/react-dropdown-menu";
import { ForwardRefExoticComponent, RefAttributes } from "react";
import { keyframes } from "@emotion/react";
import { ThemeUIStyleObject, jsx } from "theme-ui";
import { theme } from "../theme";
interface StyledProps {
sx?: ThemeUIStyleObject;
}
const Root = DropdownMenu.Root;
const Trigger = DropdownMenu.Trigger;
const slideUpAndFade = keyframes({
"0%": { opacity: 0, transform: "translateY(2px)" },
"100%": { opacity: 1, transform: "translateY(0)" },
});
const slideRightAndFade = keyframes({
"0%": { opacity: 0, transform: "translateX(-2px)" },
"100%": { opacity: 1, transform: "translateX(0)" },
});
const slideDownAndFade = keyframes({
"0%": { opacity: 0, transform: "translateY(-2px)" },
"100%": { opacity: 1, transform: "translateY(0)" },
});
const slideLeftAndFade = keyframes({
"0%": { opacity: 0, transform: "translateX(2px)" },
"100%": { opacity: 1, transform: "translateX(0)" },
});
const bounce = keyframes`
from, 20%, 53%, 80%, to {
transform: translate3d(0,0,0);
}
40%, 43% {
transform: translate3d(0, -30px, 0);
}
70% {
transform: translate3d(0, -15px, 0);
}
90% {
transform: translate3d(0,-4px,0);
}
`;
const animationTypeOne = keyframes({
"0%": {
opacity: 1,
},
"20%": {
opacity: 0,
},
"100%": {
opacity: 1,
},
});
const fadeIn = keyframes({ from: { opacity: 0 }, to: { opacity: 1 } });
const itemStyles: ThemeUIStyleObject = {
all: "unset",
fontSize: 1,
lineHeight: 1,
color: (theme) => theme.rawColors?.modes?.light?.text,
borderRadius: 3,
display: "flex",
alignItems: "center",
height: "auto",
padding: "10px 5px",
position: "relative",
paddingLeft: 2,
userSelect: "none",
"&[data-disabled]": {
color: (theme) => theme.rawColors?.modes?.light.muted,
pointerEvents: "none",
},
"&:focus": {
backgroundColor: (theme) => theme.rawColors?.modes?.light?.text,
color: (theme) => theme.rawColors?.modes?.light?.background,
},
};
const Content = (props: DropdownMenu.DropdownMenuContentProps) => (
<DropdownMenu.Content
{...props}
sx={{
minWidth: 220,
backgroundColor: (theme) => theme.rawColors?.modes?.light?.background,
borderRadius: 6,
padding: 1,
boxShadow:
"0px 10px 38px -10px rgba(22, 23, 24, 0.35), 0px 10px 20px -15px rgba(22, 23, 24, 0.2)",
"@media (prefers-reduced-motion: no-preference)": {
animationDuration: "400ms",
animationTimingFunction: "cubic-bezier(0.16, 1, 0.3, 1)",
willChange: "transform, opacity",
'&[data-state="open"]': {
'&[data-side="top"]': {
animationName: slideDownAndFade.toString(),
},
'&[data-side="right"]': {
animationName: slideLeftAndFade.toString(),
},
'&[data-side="bottom"]': {
animationName: slideUpAndFade.toString(),
},
'&[data-side="left"]': {
animationName: slideRightAndFade.toString(),
},
},
},
}}
/>
);
const Item = (props: DropdownMenu.MenuItemProps) => (
<DropdownMenu.Item {...props} sx={{ ...itemStyles }} />
);
const Label = (props: DropdownMenu.MenuLabelProps) => (
<DropdownMenu.Label {...props} sx={{ ...itemStyles }} />
);
const Group = DropdownMenu.Group;
const Separator = DropdownMenu.Separator;
const Arrow = (props: DropdownMenu.MenuArrowProps) => (
<DropdownMenu.Arrow
{...props}
sx={{
fill: (theme) => theme.rawColors?.modes?.light.background,
}}
/>
);
const Dropdown = {
Root,
Label,
Trigger,
Content,
Item,
Arrow,
Group,
Separator,
};
export default Dropdown;

31
components/Footer.tsx Normal file
View File

@@ -0,0 +1,31 @@
import { Box } from "theme-ui";
import { useSnapshot } from "valtio";
import { state } from "../state";
const Footer = () => {
const snap = useSnapshot(state);
return (
<Box as="footer" sx={{ display: "flex" }}>
<Box
as="pre"
sx={{
borderRadius: "6px",
backgroundColor: "#242426",
display: "flex",
width: "100%",
height: "160px",
fontFamily: "monospace",
fontSize: 0,
overflowY: "scroll",
py: 3,
px: 3,
m: 3,
}}
>
{snap.logs.map((log, index) => index + 1 + ": " + log + "\n")}
</Box>
</Box>
);
};
export default Footer;

View File

@@ -0,0 +1,73 @@
/** @jsxImportSource theme-ui */
import { useRef } from "react";
import { useSnapshot } from "valtio";
import Editor from "@monaco-editor/react";
import type monaco from "monaco-editor";
import { useColorMode } from "@theme-ui/color-modes";
import { Button, Box } from "theme-ui";
import { ArrowRight } from "phosphor-react";
import { state } from "../state";
import dark from "../theme/editor/amy.json";
import light from "../theme/editor/xcode_default.json";
const HooksEditor = () => {
const editorRef = useRef<monaco.editor.IStandaloneCodeEditor>();
const [mode, setColorMode] = useColorMode();
const snap = useSnapshot(state);
return (
<Box sx={{ flex: 1, display: "flex", position: "relative" }}>
<Editor
defaultLanguage={snap.files?.[snap.active]?.language}
path={snap.files?.[snap.active]?.name}
defaultValue={snap.files?.[snap.active]?.content}
beforeMount={(monaco) => {
// @ts-expect-error
monaco.editor.defineTheme("dark", dark);
// @ts-expect-error
monaco.editor.defineTheme("light", light);
}}
onMount={(editor, monaco) => {
editorRef.current = editor;
editor.updateOptions({
minimap: {
enabled: false,
},
});
editor.addCommand(
monaco.KeyMod.CtrlCmd | monaco.KeyCode.KEY_S,
() => {
if (
state.files &&
state.files.length > 0 &&
state.files[snap.active]
) {
console.log(
`File ${snap.files[snap.active].name} saved successfully ✅`
);
state.files[snap.active].content = editor.getValue();
}
}
);
}}
theme={mode === "dark" ? "dark" : "light"}
wrapperProps={{ style: { display: "flex", flex: 1 } }}
/>
<Button
sx={{
position: "absolute",
bottom: 1,
left: 3,
alignItems: "center",
display: "flex",
cursor: "pointer",
}}
>
Compile{" "}
<ArrowRight sx={{ mb: "0px", ml: 2 }} weight="bold" size="20px" />
</Button>
</Box>
);
};
export default HooksEditor;

29
components/Logo.tsx Normal file
View File

@@ -0,0 +1,29 @@
/** @jsxImportSource theme-ui */
import { useColorMode } from "theme-ui";
function Logo(props: React.SVGProps<SVGSVGElement>) {
const [mode] = useColorMode();
return (
<svg
width="1em"
height="1em"
viewBox="0 0 28 22"
fill="none"
xmlns="http://www.w3.org/2000/svg"
{...props}
>
<path
d="M19.603 3.87h2.3l-4.786 4.747a4.466 4.466 0 01-6.276 0L6.054 3.871h2.3l3.636 3.605a2.828 2.828 0 003.975 0l3.638-3.605zM8.325 17.069h-2.3l4.816-4.776a4.466 4.466 0 016.276 0l4.816 4.776h-2.3l-3.665-3.635a2.828 2.828 0 00-3.975 0l-3.668 3.635z"
sx={{ fill: "text" }}
/>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M1.556 9.769h4.751v1.555H1.556v10.072H0V0h1.556v9.769zM26.444 9.769h-4.751v1.555h4.751v10.072H28V0h-1.556v9.769z"
sx={{ fill: "text" }}
/>
</svg>
);
}
export default Logo;

127
components/Navigation.tsx Normal file
View File

@@ -0,0 +1,127 @@
/** @jsxImportSource theme-ui */
import Link from "next/link";
import { DownloadSimple, Plus, Share, BookOpen } from "phosphor-react";
import {
Container,
Box,
Heading,
Button,
Spinner,
useColorMode,
} from "theme-ui";
import { useSnapshot } from "valtio";
import { Sun, MoonStars } from "phosphor-react";
import Image from "next/image";
import { useSession, signIn, signOut } from "next-auth/react";
import Dropdown from "./DropdownMenu";
import Stack from "./Stack";
import Logo from "./Logo";
// import Button from "./Button";
import { state } from "../state";
const Navigation = () => {
const snap = useSnapshot(state);
const [mode, setColorMode] = useColorMode();
const { data: session, status } = useSession();
console.log(session);
return (
<Box
as="nav"
sx={{
display: "flex",
height: "60px",
bg: "background",
// borderBottom: "1px solid",
borderColor: "text",
}}
>
<Container sx={{ display: "flex", alignItems: "center", py: 2 }}>
<Link href="/" passHref>
<Box as="a" sx={{ display: "flex", alignItems: "center" }}>
<Logo width="30px" height="30px" />
<Heading as="h3" sx={{ fontWeight: "bold", ml: 2 }}>
XRPL Hooks
</Heading>
</Box>
</Link>
<Box sx={{ ml: 3 }}></Box>
<Stack sx={{ ml: 3 }} spacing={2}>
{state.loading && "loading"}
{snap.files &&
snap.files.length > 0 &&
snap.files?.map((file, index) => (
<Button
onClick={() => (state.active = index)}
key={file.name}
variant={snap.active === index ? "secondary" : "muted"}
>
{file.name}
</Button>
))}
</Stack>
<Stack sx={{ color: "text", ml: "auto" }}>
<Plus sx={{ display: "flex" }} size="20px" />
<Share sx={{ display: "flex" }} size="20px" />
<DownloadSimple sx={{ display: "flex" }} size="20px" />
<Box
color="text"
onClick={(e) => {
setColorMode(mode === "light" ? "dark" : "light");
}}
sx={{
display: "flex",
marginLeft: "auto",
cursor: "pointer",
alignItems: "center",
justifyContent: "center",
mb: 1,
}}
>
{mode === "dark" ? <Sun size="20px" /> : <MoonStars size="20px" />}
</Box>
{status === "authenticated" && (
<Dropdown.Root>
<Dropdown.Trigger asChild>
<Box sx={{ borderRadius: "100%", overflow: "hidden" }}>
<Image
src={session?.user?.image || ""}
width="30px"
height="30px"
objectFit="cover"
alt="User avatar"
/>
</Box>
</Dropdown.Trigger>
<Dropdown.Content>
<Dropdown.Item onClick={() => signOut()}>Log out</Dropdown.Item>
<Dropdown.Arrow offset={10} />
</Dropdown.Content>
</Dropdown.Root>
)}
{status === "unauthenticated" && (
<Button
sx={{ size: "sm", cursor: "pointer" }}
onClick={() => signIn("github")}
>
Github Login
</Button>
)}
{status === "loading" && <Spinner size="20px" />}
{/* <Box
sx={{
border: "1px solid",
borderRadius: "3px",
borderColor: "text",
p: 1,
}}
>
<BookOpen sx={{ display: "flex" }} size="20px" />
</Box> */}
</Stack>
</Container>
</Box>
);
};
export default Navigation;

38
components/Stack.tsx Normal file
View File

@@ -0,0 +1,38 @@
import { Children } from "react";
import { Flex, Box, ThemeUIStyleObject, BoxProps } from "theme-ui";
import { useBreakpointIndex } from "@theme-ui/match-media";
const Stack: React.FC<
BoxProps & {
spacing?: (number | string | null)[] | string | number;
direction?: ("column" | "row") | ("column" | "row" | null)[];
sx?: ThemeUIStyleObject;
}
> = ({ spacing = 3, direction = "row", sx, children, ...rest }) => {
const breakpointIndex = useBreakpointIndex();
const currentDirection = Array.isArray(direction)
? direction[breakpointIndex]
: direction;
const childrenLength = Array.isArray(children) ? children.length : null;
return (
<Box
{...rest}
sx={{
display: "flex",
flexDirection: direction,
...sx,
}}
>
{Children.map(children, (child, index) => (
<Box
mt={currentDirection === "column" && index !== 0 ? spacing : 0}
ml={currentDirection === "row" && index !== 0 ? spacing : 0}
>
{child}
</Box>
))}
</Box>
);
};
export default Stack;

View File

@@ -1,4 +1,7 @@
/** @type {import('next').NextConfig} */
module.exports = {
reactStrictMode: true,
images: {
domains: ['avatars.githubusercontent.com'],
},
}

View File

@@ -9,9 +9,24 @@
"lint": "next lint"
},
"dependencies": {
"next": "11.1.2",
"@mattjennings/react-modal": "^1.0.3",
"@monaco-editor/react": "^4.3.1",
"@octokit/core": "^3.5.1",
"@radix-ui/react-dropdown-menu": "^0.1.1",
"@theme-ui/color": "^0.11.3",
"@theme-ui/match-media": "^0.11.3",
"@wasmer/wasi": "^0.12.0",
"@wasmer/wasm-transformer": "^0.12.0",
"@wasmer/wasmfs": "^0.12.0",
"monaco-editor": "^0.29.1",
"next": "^12.0.1",
"next-auth": "^4.0.0-beta.5",
"octokit": "^1.7.0",
"phosphor-react": "^1.3.1",
"react": "17.0.2",
"react-dom": "17.0.2"
"react-dom": "17.0.2",
"theme-ui": "^0.11.3",
"valtio": "^1.2.5"
},
"devDependencies": {
"@types/react": "17.0.31",

47
pages/[[...index]].tsx Normal file
View File

@@ -0,0 +1,47 @@
/** @jsxImportSource theme-ui */
import type { GetStaticPaths, GetStaticProps, NextPage } from "next";
import Head from "next/head";
import { Box } from "theme-ui";
import { useRouter } from "next/router";
import HooksEditor from "../components/HooksEditor";
import { useEffect } from "react";
import { fetchFiles } from "../state";
import Footer from "../components/Footer";
const Home: NextPage = () => {
const router = useRouter();
const index = router.query.index;
const gistId = index && Array.isArray(index) ? index[0] : "";
useEffect(() => {
fetchFiles(gistId);
}, [gistId]);
return (
<>
<Head>
<title>XRPL Hooks Playground</title>
</Head>
<main sx={{ display: "flex", flex: 1 }}>
<HooksEditor />
</main>
<Footer />
</>
);
};
export default Home;
export const getStaticPaths: GetStaticPaths = async () => {
// ...
return { paths: [], fallback: "blocking" };
};
export const getStaticProps: GetStaticProps = async (context) => {
// ...
return {
props: {},
revalidate: 60,
};
};

View File

@@ -1,7 +1,22 @@
import '../styles/globals.css'
import type { AppProps } from 'next/app'
/** @jsxImportSource theme-ui */
import "../styles/globals.css";
import type { AppProps } from "next/app";
import { ThemeProvider } from "theme-ui";
import { SessionProvider } from "next-auth/react";
function MyApp({ Component, pageProps }: AppProps) {
return <Component {...pageProps} />
import { theme } from "../theme";
import Navigation from "../components/Navigation";
function MyApp({ Component, pageProps: { session, ...pageProps } }: AppProps) {
return (
<>
<SessionProvider session={session}>
<ThemeProvider theme={theme}>
<Navigation />
<Component {...pageProps} />
</ThemeProvider>
</SessionProvider>
</>
);
}
export default MyApp
export default MyApp;

41
pages/_document.tsx Normal file
View File

@@ -0,0 +1,41 @@
import Document, {
Html,
Head,
Main,
NextScript,
DocumentContext,
} from "next/document";
class MyDocument extends Document {
static async getInitialProps(ctx: DocumentContext) {
const initialProps = await Document.getInitialProps(ctx);
return initialProps;
}
render() {
return (
<Html>
<Head>
<meta name="description" content="Playground for XRPL Hooks" />
<link rel="icon" href="/favicon.ico" />
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link
rel="preconnect"
href="https://fonts.gstatic.com"
crossOrigin=""
/>
<link
href="https://fonts.googleapis.com/css2?family=Roboto+Mono:ital@0;1&family=Work+Sans:wght@400;600;700&display=swap"
rel="stylesheet"
/>
</Head>
<body>
<Main />
<NextScript />
</body>
</Html>
);
}
}
export default MyDocument;

View File

@@ -0,0 +1,49 @@
import NextAuth from "next-auth"
import GithubProvider from "next-auth/providers/github"
export default NextAuth({
// Configure one or more authentication providers
providers: [
// GithubProvider({
// clientId: process.env.GITHUB_ID,
// clientSecret: process.env.GITHUB_SECRET,
// // @ts-expect-error
// scope: 'user,gist'
// }),
{
id: "github",
name: "GitHub",
type: "oauth",
clientId: process.env.GITHUB_ID,
clientSecret: process.env.GITHUB_SECRET,
authorization: "https://github.com/login/oauth/authorize?scope=read:user+user:email+gist",
token: "https://github.com/login/oauth/access_token",
userinfo: "https://api.github.com/user",
profile(profile) {
console.log(profile)
return {
id: profile.id.toString(),
name: profile.name || profile.login,
email: profile.email,
image: profile.avatar_url,
}
},
}
// ...add more providers here
],
callbacks: {
async jwt({ token, user, account, profile, isNewUser }) {
console.log('jwt', { token, account })
if (account && account.access_token) {
token.accessToken = account.access_token;
}
return token
},
async session({ session, token }) {
console.log('session', { token, session })
session.accessToken = token.accessToken;
return session
}
},
})

View File

@@ -1,72 +0,0 @@
import type { NextPage } from 'next'
import Head from 'next/head'
import Image from 'next/image'
import styles from '../styles/Home.module.css'
const Home: NextPage = () => {
return (
<div className={styles.container}>
<Head>
<title>Create Next App</title>
<meta name="description" content="Generated by create next app" />
<link rel="icon" href="/favicon.ico" />
</Head>
<main className={styles.main}>
<h1 className={styles.title}>
Welcome to <a href="https://nextjs.org">Next.js!</a>
</h1>
<p className={styles.description}>
Get started by editing{' '}
<code className={styles.code}>pages/index.js</code>
</p>
<div className={styles.grid}>
<a href="https://nextjs.org/docs" className={styles.card}>
<h2>Documentation &rarr;</h2>
<p>Find in-depth information about Next.js features and API.</p>
</a>
<a href="https://nextjs.org/learn" className={styles.card}>
<h2>Learn &rarr;</h2>
<p>Learn about Next.js in an interactive course with quizzes!</p>
</a>
<a
href="https://github.com/vercel/next.js/tree/master/examples"
className={styles.card}
>
<h2>Examples &rarr;</h2>
<p>Discover and deploy boilerplate example Next.js projects.</p>
</a>
<a
href="https://vercel.com/new?utm_source=create-next-app&utm_medium=default-template&utm_campaign=create-next-app"
className={styles.card}
>
<h2>Deploy &rarr;</h2>
<p>
Instantly deploy your Next.js site to a public URL with Vercel.
</p>
</a>
</div>
</main>
<footer className={styles.footer}>
<a
href="https://vercel.com?utm_source=create-next-app&utm_medium=default-template&utm_campaign=create-next-app"
target="_blank"
rel="noopener noreferrer"
>
Powered by{' '}
<span className={styles.logo}>
<Image src="/vercel.svg" alt="Vercel Logo" width={72} height={16} />
</span>
</a>
</footer>
</div>
)
}
export default Home

6
public/hooks-logo.svg Normal file
View File

@@ -0,0 +1,6 @@
<svg width="28" height="22" viewBox="0 0 28 22" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M19.6028 3.87061H21.9021L17.1171 8.61699C15.3842 10.3349 12.5747 10.3349 10.8406 8.61699L6.05377 3.87061H8.35492L11.9903 7.47615C12.5199 7.99913 13.2338 8.2923 13.9775 8.2923C14.7211 8.2923 15.435 7.99913 15.9646 7.47615L19.6028 3.87061Z" fill="white"/>
<path d="M8.3255 17.0685H6.02466L10.8407 12.2929C12.5736 10.5749 15.3831 10.5749 17.1172 12.2929L21.9332 17.0685H19.6339L15.9675 13.4337C15.4378 12.9107 14.724 12.6175 13.9803 12.6175C13.2367 12.6175 12.5228 12.9107 11.9932 13.4337L8.3255 17.0685Z" fill="white"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M1.5556 9.76858L6.30711 9.76858L6.30711 11.3241L1.5556 11.3241L1.5556 21.396L4.06715e-05 21.396L4.05312e-05 -3.17035e-07L1.5556 -2.38842e-07L1.5556 9.76858Z" fill="white"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M26.4443 9.76858L21.6928 9.76858L21.6928 11.3241L26.4443 11.3241L26.4443 21.396L27.9998 21.396L27.9998 -3.17035e-07L26.4443 -2.38842e-07L26.4443 9.76858Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

105
state.ts Normal file
View File

@@ -0,0 +1,105 @@
import { proxy } from 'valtio';
import { devtools } from 'valtio/utils';
import { Octokit } from '@octokit/core';
const octokit = new Octokit();
interface Files {
name: string,
language: string,
content: string
}
interface IState {
files: {
name: string;
language: string;
content: string;
}[] | [],
active: number;
loading: boolean;
logs: string[];
}
const initFiles = [
{
name: 'hello.c',
language: 'c',
content: `
#include <stdio.h>
int main() {
// printf() displays the string inside quotation
printf("Hello, World!");
return 0;
}
`,
},
{
name: 'another.c',
language: 'c',
content: `
#include <stdio.h>
int main()
{
/* printf function displays the content that is
* passed between the double quotes.
*/
printf("Hello World");
return 0;
}
`,
}
];
const state = proxy<IState>({
files: [],
active: 0,
loading: false,
logs: []
});
// state.files = initFiles;
// const initState = ({ gistId }: { gistId?: string }) => {
// if (!gistId) {
// return initialState;
// }
// }
// const state = initialState;
export const fetchFiles = (gistId: string) => {
if (gistId) {
console.log('callling')
octokit.request("GET /gists/{gist_id}", { gist_id: gistId }).then(res => {
state.logs.push('Fetching files from Github Gists...');
if (res.data.files && Object.keys(res.data.files).length > 0) {
const files = Object.keys(res.data.files).map(filename => ({
name: res.data.files?.[filename]?.filename || 'noname.c',
language: res.data.files?.[filename]?.language?.toLowerCase() || '',
content: res.data.files?.[filename]?.content || ''
}))
state.files = initFiles
state.loading = false;
if (files.length > 0) {
state.logs.push('Fetched successfully ✅')
state.files = files;
return
}
return state.files = initFiles
}
}).catch(err => {
state.loading = false;
return state.files = initFiles
})
return
}
state.loading = false;
return state.files = initFiles
}
const unsub = devtools(state, 'Files State')
export { state };

View File

@@ -1,9 +1,11 @@
html,
body {
body,
#__next {
padding: 0;
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
min-height: 100vh;
display: flex;
flex-direction: column;
}
a {

191
theme/editor/amy.json Normal file
View File

@@ -0,0 +1,191 @@
{
"base": "vs-dark",
"inherit": true,
"rules": [
{
"background": "200020",
"token": ""
},
{
"foreground": "404080",
"background": "200020",
"fontStyle": "italic",
"token": "comment.block"
},
{
"foreground": "999999",
"token": "string"
},
{
"foreground": "707090",
"token": "constant.language"
},
{
"foreground": "7090b0",
"token": "constant.numeric"
},
{
"fontStyle": "bold",
"token": "constant.numeric.integer.int32"
},
{
"fontStyle": "italic",
"token": "constant.numeric.integer.int64"
},
{
"fontStyle": "bold italic",
"token": "constant.numeric.integer.nativeint"
},
{
"fontStyle": "underline",
"token": "constant.numeric.floating-point.ocaml"
},
{
"foreground": "666666",
"token": "constant.character"
},
{
"foreground": "8080a0",
"token": "constant.language.boolean"
},
{
"foreground": "008080",
"token": "variable.language"
},
{
"foreground": "008080",
"token": "variable.other"
},
{
"foreground": "a080ff",
"token": "keyword"
},
{
"foreground": "a0a0ff",
"token": "keyword.operator"
},
{
"foreground": "d0d0ff",
"token": "keyword.other.decorator"
},
{
"fontStyle": "underline",
"token": "keyword.operator.infix.floating-point.ocaml"
},
{
"fontStyle": "underline",
"token": "keyword.operator.prefix.floating-point.ocaml"
},
{
"foreground": "c080c0",
"token": "keyword.other.directive"
},
{
"foreground": "c080c0",
"fontStyle": "underline",
"token": "keyword.other.directive.line-number"
},
{
"foreground": "80a0ff",
"token": "keyword.control"
},
{
"foreground": "b0fff0",
"token": "storage"
},
{
"foreground": "60b0ff",
"token": "entity.name.type.variant"
},
{
"foreground": "60b0ff",
"fontStyle": "italic",
"token": "storage.type.variant.polymorphic"
},
{
"foreground": "60b0ff",
"fontStyle": "italic",
"token": "entity.name.type.variant.polymorphic"
},
{
"foreground": "b000b0",
"token": "entity.name.type.module"
},
{
"foreground": "b000b0",
"fontStyle": "underline",
"token": "entity.name.type.module-type.ocaml"
},
{
"foreground": "a00050",
"token": "support.other"
},
{
"foreground": "70e080",
"token": "entity.name.type.class"
},
{
"foreground": "70e0a0",
"token": "entity.name.type.class-type"
},
{
"foreground": "50a0a0",
"token": "entity.name.function"
},
{
"foreground": "80b0b0",
"token": "variable.parameter"
},
{
"foreground": "3080a0",
"token": "entity.name.type.token"
},
{
"foreground": "3cb0d0",
"token": "entity.name.type.token.reference"
},
{
"foreground": "90e0e0",
"token": "entity.name.function.non-terminal"
},
{
"foreground": "c0f0f0",
"token": "entity.name.function.non-terminal.reference"
},
{
"foreground": "009090",
"token": "entity.name.tag"
},
{
"background": "200020",
"token": "support.constant"
},
{
"foreground": "400080",
"background": "ffff00",
"fontStyle": "bold",
"token": "invalid.illegal"
},
{
"foreground": "200020",
"background": "cc66ff",
"token": "invalid.deprecated"
},
{
"background": "40008054",
"token": "source.camlp4.embedded"
},
{
"foreground": "805080",
"token": "punctuation"
}
],
"colors": {
"editor.foreground": "#D0D0FF",
"editor.background": "#000000",
"editor.selectionBackground": "#ffffff30",
"editor.lineHighlightBackground": "#ffffff20",
"editorCursor.foreground": "#7070FF",
"editorWhitespace.foreground": "#BFBFBF"
}
}

312
theme/editor/sunburst.json Normal file
View File

@@ -0,0 +1,312 @@
{
"base": "vs-dark",
"inherit": true,
"rules": [
{
"background": "000000",
"token": ""
},
{
"foreground": "aeaeae",
"fontStyle": "italic",
"token": "comment"
},
{
"foreground": "3387cc",
"token": "constant"
},
{
"foreground": "89bdff",
"token": "entity"
},
{
"foreground": "e28964",
"token": "keyword"
},
{
"foreground": "99cf50",
"token": "storage"
},
{
"foreground": "65b042",
"token": "string"
},
{
"foreground": "9b859d",
"token": "support"
},
{
"foreground": "3e87e3",
"token": "variable"
},
{
"foreground": "fd5ff1",
"fontStyle": "italic underline",
"token": "invalid.deprecated"
},
{
"foreground": "fd5ff1",
"background": "562d56bf",
"token": "invalid.illegal"
},
{
"background": "b1b3ba08",
"token": "text source"
},
{
"foreground": "9b5c2e",
"fontStyle": "italic",
"token": "entity.other.inherited-class"
},
{
"foreground": "daefa3",
"token": "string.quoted source"
},
{
"foreground": "ddf2a4",
"token": "string constant"
},
{
"foreground": "e9c062",
"token": "string.regexp"
},
{
"foreground": "cf7d34",
"token": "string.regexp constant.character.escape"
},
{
"foreground": "cf7d34",
"token": "string.regexp source.ruby.embedded"
},
{
"foreground": "cf7d34",
"token": "string.regexp string.regexp.arbitrary-repitition"
},
{
"foreground": "8a9a95",
"token": "string variable"
},
{
"foreground": "dad085",
"token": "support.function"
},
{
"foreground": "cf6a4c",
"token": "support.constant"
},
{
"foreground": "8996a8",
"token": "meta.preprocessor.c"
},
{
"foreground": "afc4db",
"token": "meta.preprocessor.c keyword"
},
{
"fontStyle": "underline",
"token": "entity.name.type"
},
{
"foreground": "676767",
"fontStyle": "italic",
"token": "meta.cast"
},
{
"foreground": "494949",
"token": "meta.sgml.html meta.doctype"
},
{
"foreground": "494949",
"token": "meta.sgml.html meta.doctype entity"
},
{
"foreground": "494949",
"token": "meta.sgml.html meta.doctype string"
},
{
"foreground": "494949",
"token": "meta.xml-processing"
},
{
"foreground": "494949",
"token": "meta.xml-processing entity"
},
{
"foreground": "494949",
"token": "meta.xml-processing string"
},
{
"foreground": "89bdff",
"token": "meta.tag"
},
{
"foreground": "89bdff",
"token": "meta.tag entity"
},
{
"foreground": "e0c589",
"token": "source entity.name.tag"
},
{
"foreground": "e0c589",
"token": "source entity.other.attribute-name"
},
{
"foreground": "e0c589",
"token": "meta.tag.inline"
},
{
"foreground": "e0c589",
"token": "meta.tag.inline entity"
},
{
"foreground": "e18964",
"token": "entity.name.tag.namespace"
},
{
"foreground": "e18964",
"token": "entity.other.attribute-name.namespace"
},
{
"foreground": "cda869",
"token": "meta.selector.css entity.name.tag"
},
{
"foreground": "8f9d6a",
"token": "meta.selector.css entity.other.attribute-name.tag.pseudo-class"
},
{
"foreground": "8b98ab",
"token": "meta.selector.css entity.other.attribute-name.id"
},
{
"foreground": "9b703f",
"token": "meta.selector.css entity.other.attribute-name.class"
},
{
"foreground": "c5af75",
"token": "support.type.property-name.css"
},
{
"foreground": "f9ee98",
"token": "meta.property-group support.constant.property-value.css"
},
{
"foreground": "f9ee98",
"token": "meta.property-value support.constant.property-value.css"
},
{
"foreground": "8693a5",
"token": "meta.preprocessor.at-rule keyword.control.at-rule"
},
{
"foreground": "dd7b3b",
"token": "meta.property-value support.constant.named-color.css"
},
{
"foreground": "dd7b3b",
"token": "meta.property-value constant"
},
{
"foreground": "8f9d6a",
"token": "meta.constructor.argument.css"
},
{
"foreground": "f8f8f8",
"background": "0e2231",
"fontStyle": "italic",
"token": "meta.diff"
},
{
"foreground": "f8f8f8",
"background": "0e2231",
"fontStyle": "italic",
"token": "meta.diff.header"
},
{
"foreground": "f8f8f8",
"background": "420e09",
"token": "markup.deleted"
},
{
"foreground": "f8f8f8",
"background": "4a410d",
"token": "markup.changed"
},
{
"foreground": "f8f8f8",
"background": "253b22",
"token": "markup.inserted"
},
{
"foreground": "e9c062",
"fontStyle": "italic",
"token": "markup.italic"
},
{
"foreground": "e9c062",
"fontStyle": "bold",
"token": "markup.bold"
},
{
"foreground": "e18964",
"fontStyle": "underline",
"token": "markup.underline"
},
{
"foreground": "e1d4b9",
"background": "fee09c12",
"fontStyle": "italic",
"token": "markup.quote"
},
{
"foreground": "fedcc5",
"background": "632d04",
"token": "markup.heading"
},
{
"foreground": "fedcc5",
"background": "632d04",
"token": "markup.heading entity"
},
{
"foreground": "e1d4b9",
"token": "markup.list"
},
{
"foreground": "578bb3",
"background": "b1b3ba08",
"token": "markup.raw"
},
{
"foreground": "f67b37",
"fontStyle": "italic",
"token": "markup comment"
},
{
"foreground": "60a633",
"background": "242424",
"token": "meta.separator"
},
{
"background": "eeeeee29",
"token": "meta.line.entry.logfile"
},
{
"background": "eeeeee29",
"token": "meta.line.exit.logfile"
},
{
"background": "751012",
"token": "meta.line.error.logfile"
}
],
"colors": {
"editor.foreground": "#F8F8F8",
"editor.background": "#000000",
"editor.selectionBackground": "#DDF0FF33",
"editor.lineHighlightBackground": "#FFFFFF0D",
"editorCursor.foreground": "#A7A7A7",
"editorWhitespace.foreground": "#CAE2FB3D"
}
}

View File

@@ -0,0 +1,196 @@
{
"base": "vs-dark",
"inherit": true,
"rules": [
{
"background": "000000",
"token": ""
},
{
"foreground": "ffffff",
"background": "0f0f0f",
"token": "text"
},
{
"background": "000000",
"token": "source.ruby.rails.embedded.html"
},
{
"foreground": "ffffff",
"background": "101010",
"token": "text.html.ruby"
},
{
"foreground": "ccff33",
"token": "constant.numeric.ruby"
},
{
"foreground": "ffffff",
"background": "000000",
"token": "source"
},
{
"foreground": "9933cc",
"token": "comment"
},
{
"foreground": "339999",
"token": "constant"
},
{
"foreground": "ff6600",
"token": "keyword"
},
{
"foreground": "edf8f9",
"token": "keyword.preprocessor"
},
{
"foreground": "ffffff",
"token": "keyword.preprocessor directive"
},
{
"foreground": "ffcc00",
"token": "entity.name.function"
},
{
"foreground": "ffcc00",
"token": "storage.type.function.js"
},
{
"fontStyle": "italic",
"token": "variable.parameter"
},
{
"foreground": "772cb7",
"background": "070707",
"token": "source comment.block"
},
{
"foreground": "ffffff",
"token": "variable.other"
},
{
"foreground": "999966",
"token": "support.function.activerecord.rails"
},
{
"foreground": "66ff00",
"token": "string"
},
{
"foreground": "aaaaaa",
"token": "string constant.character.escape"
},
{
"foreground": "000000",
"background": "cccc33",
"token": "string.interpolated"
},
{
"foreground": "44b4cc",
"token": "string.regexp"
},
{
"foreground": "cccc33",
"token": "string.literal"
},
{
"foreground": "555555",
"token": "string.interpolated constant.character.escape"
},
{
"fontStyle": "underline",
"token": "entity.name.class"
},
{
"fontStyle": "underline",
"token": "support.class.js"
},
{
"fontStyle": "italic underline",
"token": "entity.other.inherited-class"
},
{
"foreground": "ff6600",
"token": "meta.tag.inline.any.html"
},
{
"foreground": "ff6600",
"token": "meta.tag.block.any.html"
},
{
"foreground": "99cc99",
"fontStyle": "italic",
"token": "entity.other.attribute-name"
},
{
"foreground": "dde93d",
"token": "keyword.other"
},
{
"foreground": "ff6600",
"token": "meta.selector.css"
},
{
"foreground": "ff6600",
"token": "entity.other.attribute-name.pseudo-class.css"
},
{
"foreground": "ff6600",
"token": "entity.name.tag.wildcard.css"
},
{
"foreground": "ff6600",
"token": "entity.other.attribute-name.id.css"
},
{
"foreground": "ff6600",
"token": "entity.other.attribute-name.class.css"
},
{
"foreground": "999966",
"token": "support.type.property-name.css"
},
{
"foreground": "ffffff",
"token": "keyword.other.unit.css"
},
{
"foreground": "ffffff",
"token": "constant.other.rgb-value.css"
},
{
"foreground": "ffffff",
"token": "constant.numeric.css"
},
{
"foreground": "ffffff",
"token": "support.function.event-handler.js"
},
{
"foreground": "ffffff",
"token": "keyword.operator.js"
},
{
"foreground": "cccc66",
"token": "keyword.control.js"
},
{
"foreground": "ffffff",
"token": "support.class.prototype.js"
},
{
"foreground": "ff6600",
"token": "object.property.function.prototype.js"
}
],
"colors": {
"editor.foreground": "#FFFFFF",
"editor.background": "#000000",
"editor.selectionBackground": "#35493CE0",
"editor.lineHighlightBackground": "#333300",
"editorCursor.foreground": "#FFFFFF",
"editorWhitespace.foreground": "#404040"
}
}

View File

@@ -0,0 +1,98 @@
{
"base": "vs",
"inherit": true,
"rules": [
{
"background": "FFFFFF",
"token": ""
},
{
"foreground": "008e00",
"token": "comment"
},
{
"foreground": "7d4726",
"token": "meta.preprocessor"
},
{
"foreground": "7d4726",
"token": "keyword.control.import"
},
{
"foreground": "df0002",
"token": "string"
},
{
"foreground": "3a00dc",
"token": "constant.numeric"
},
{
"foreground": "c800a4",
"token": "constant.language"
},
{
"foreground": "275a5e",
"token": "constant.character"
},
{
"foreground": "275a5e",
"token": "constant.other"
},
{
"foreground": "c800a4",
"token": "variable.language"
},
{
"foreground": "c800a4",
"token": "variable.other"
},
{
"foreground": "c800a4",
"token": "keyword"
},
{
"foreground": "c900a4",
"token": "storage"
},
{
"foreground": "438288",
"token": "entity.name.class"
},
{
"foreground": "790ead",
"token": "entity.name.tag"
},
{
"foreground": "450084",
"token": "entity.other.attribute-name"
},
{
"foreground": "450084",
"token": "support.function"
},
{
"foreground": "450084",
"token": "support.constant"
},
{
"foreground": "790ead",
"token": "support.type"
},
{
"foreground": "790ead",
"token": "support.class"
},
{
"foreground": "790ead",
"token": "support.other.variable"
}
],
"colors": {
"editor.foreground": "#000000",
"editor.background": "#FFFFFF",
"editor.selectionBackground": "#B5D5FF",
"editor.lineHighlightBackground": "#00000012",
"editorCursor.foreground": "#000000",
"editorWhitespace.foreground": "#BFBFBF"
}
}

180
theme/index.ts Normal file
View File

@@ -0,0 +1,180 @@
import type { Theme } from "theme-ui";
import { darken, lighten } from '@theme-ui/color'
const makeTheme = <T extends Theme>(t: T) => t
export const theme = makeTheme({
config: {
initialColorModeName: 'light',
},
breakpoints: ['40em', '52em', '64em', '78em'],
space: [0, 4, 8, 16, 32, 64, 128, 256, 512],
fonts: {
body: 'Work Sans, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", sans-serif',
heading: 'Work Sans, sans-serif',
monospace: 'Roboto, monospace',
},
fontSizes: [12, 14, 16, 18, 20, 24, 32, 48, 64, 96],
fontWeights: {
body: 400,
heading: 400,
bold: 700,
},
layout: {
container: {
maxWidth: "100%",
width: "100%",
mx: "auto",
px: 3
}
},
lineHeights: {
body: 1.5,
heading: 0.85,
},
colors: {
text: '#000000',
background: '#FFFFFF',
primary: '#9A52FF',
secondary: '#30c',
muted: '#C6C6D3',
modes: {
dark: {
text: '#FFFFFF',
background: '#000000',
primary: '#9A52FF',
secondary: '#30c',
}
}
},
text: {
heading: {
fontFamily: 'heading',
lineHeight: 'heading',
fontWeight: 'heading',
},
monospace: {
fontWeight: 300
}
},
sizes: {
"widePlus": 2048,
"wide": 1536,
"layoutPlus": 1260,
"layout": 1024,
"copyUltra": 980,
"copyPlus": 768,
"copy": 680,
"narrowPlus": 600,
"narrow": 512,
sm: {
paddingX: 3,
paddingY: 1
},
md: {
px: 4,
py: 2
},
lg: {
px: 6,
py: 4
},
},
buttons: {
primary: {
size: 'md',
color: 'white',
bg: 'primary',
'&:hover': {
bg: darken('primary', 0.1),
borderColor: darken('primary', 0.1)
},
fontWeight: 600,
borderRadius: '3px',
fontSize: 1,
border: '1px solid',
borderColor: 'primary',
},
secondary: {
color: 'black',
bg: 'muted',
fontSize: 1,
borderRadius: '3px',
border: '1px solid',
borderColor: 'muted',
'&:hover': {
bg: darken('muted', 0.1),
borderColor: darken('muted', 0.1),
},
cursor: 'pointer'
},
muted: {
color: 'text',
bg: 'background',
fontSize: 1,
border: '1px solid',
borderColor: 'text',
borderRadius: '3px',
'&:hover': {
bg: darken('background', 0.1),
},
cursor: 'pointer'
}
},
styles: {
root: {
fontFamily: 'body',
lineHeight: 'body',
fontWeight: 'body',
},
h1: {
variant: 'text.heading',
fontSize: 5,
},
h2: {
variant: 'text.heading',
fontSize: 4,
},
h3: {
variant: 'text.heading',
fontSize: 3,
},
h4: {
variant: 'text.heading',
fontSize: 2,
},
h5: {
variant: 'text.heading',
fontSize: 1,
},
h6: {
variant: 'text.heading',
fontSize: 0,
},
pre: {
fontFamily: 'monospace',
overflowX: 'auto',
code: {
color: 'inherit',
},
},
code: {
fontFamily: 'monospace',
fontSize: 'inherit',
},
table: {
width: '100%',
borderCollapse: 'separate',
borderSpacing: 0,
},
th: {
textAlign: 'left',
borderBottomStyle: 'solid',
},
td: {
textAlign: 'left',
borderBottomStyle: 'solid',
},
},
});

View File

@@ -1,7 +1,11 @@
{
"compilerOptions": {
"target": "es5",
"lib": ["dom", "dom.iterable", "esnext"],
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
@@ -12,8 +16,15 @@
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve"
"jsx": "preserve",
"incremental": true
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
"exclude": ["node_modules"]
"include": [
"next-env.d.ts",
"**/*.ts",
"**/*.tsx"
],
"exclude": [
"node_modules"
]
}

4483
yarn.lock Normal file

File diff suppressed because it is too large Load Diff