commit ddb6f41eecc8d235c73f263b7e92e32c740ddc9f Author: MasterGordon Date: Thu Feb 20 22:57:16 2025 +0100 first commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9b1ee42 --- /dev/null +++ b/.gitignore @@ -0,0 +1,175 @@ +# Based on https://raw.githubusercontent.com/github/gitignore/main/Node.gitignore + +# Logs + +logs +_.log +npm-debug.log_ +yarn-debug.log* +yarn-error.log* +lerna-debug.log* +.pnpm-debug.log* + +# Caches + +.cache + +# Diagnostic reports (https://nodejs.org/api/report.html) + +report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json + +# Runtime data + +pids +_.pid +_.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover + +lib-cov + +# Coverage directory used by tools like istanbul + +coverage +*.lcov + +# nyc test coverage + +.nyc_output + +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) + +.grunt + +# Bower dependency directory (https://bower.io/) + +bower_components + +# node-waf configuration + +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) + +build/Release + +# Dependency directories + +node_modules/ +jspm_packages/ + +# Snowpack dependency directory (https://snowpack.dev/) + +web_modules/ + +# TypeScript cache + +*.tsbuildinfo + +# Optional npm cache directory + +.npm + +# Optional eslint cache + +.eslintcache + +# Optional stylelint cache + +.stylelintcache + +# Microbundle cache + +.rpt2_cache/ +.rts2_cache_cjs/ +.rts2_cache_es/ +.rts2_cache_umd/ + +# Optional REPL history + +.node_repl_history + +# Output of 'npm pack' + +*.tgz + +# Yarn Integrity file + +.yarn-integrity + +# dotenv environment variable files + +.env +.env.development.local +.env.test.local +.env.production.local +.env.local + +# parcel-bundler cache (https://parceljs.org/) + +.parcel-cache + +# Next.js build output + +.next +out + +# Nuxt.js build / generate output + +.nuxt +dist + +# Gatsby files + +# Comment in the public line in if your project uses Gatsby and not Next.js + +# https://nextjs.org/blog/next-9-1#public-directory-support + +# public + +# vuepress build output + +.vuepress/dist + +# vuepress v2.x temp and cache directory + +.temp + +# Docusaurus cache and generated files + +.docusaurus + +# Serverless directories + +.serverless/ + +# FuseBox cache + +.fusebox/ + +# DynamoDB Local files + +.dynamodb/ + +# TernJS port file + +.tern-port + +# Stores VSCode versions used for testing VSCode extensions + +.vscode-test + +# yarn v2 + +.yarn/cache +.yarn/unplugged +.yarn/build-state.yml +.yarn/install-state.gz +.pnp.* + +# IntelliJ based IDEs +.idea + +# Finder (MacOS) folder config +.DS_Store diff --git a/README.md b/README.md new file mode 100644 index 0000000..48a5d2f --- /dev/null +++ b/README.md @@ -0,0 +1,15 @@ +# fast-web + +To install dependencies: + +```bash +bun install +``` + +To run: + +```bash +bun run index.ts +``` + +This project was created using `bun init` in bun v1.1.29. [Bun](https://bun.sh) is a fast all-in-one JavaScript runtime. diff --git a/bun.lockb b/bun.lockb new file mode 100755 index 0000000..db61286 Binary files /dev/null and b/bun.lockb differ diff --git a/package.json b/package.json new file mode 100644 index 0000000..228135d --- /dev/null +++ b/package.json @@ -0,0 +1,20 @@ +{ + "name": "fast-web", + "module": "index.ts", + "type": "module", + "scripts": { + "start": "bun run src/index.tsx", + "dev": "bun run --hot src/index.tsx" + }, + "devDependencies": { + "@types/bun": "latest", + "csstype": "^3.1.3" + }, + "peerDependencies": { + "typescript": "^5.0.0" + }, + "dependencies": { + "lightningcss": "^1.29.1", + "serve-static-bun": "^0.5.3" + } +} diff --git a/public/assets/OFL.txt b/public/assets/OFL.txt new file mode 100644 index 0000000..e9f5f00 --- /dev/null +++ b/public/assets/OFL.txt @@ -0,0 +1,93 @@ +Copyright 2015 The Rubik Project Authors (https://github.com/googlefonts/rubik) + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +https://openfontlicense.org + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/public/assets/Rubik.ttf b/public/assets/Rubik.ttf new file mode 100644 index 0000000..bbab349 Binary files /dev/null and b/public/assets/Rubik.ttf differ diff --git a/src/components/Layout.tsx b/src/components/Layout.tsx new file mode 100644 index 0000000..48f1e80 --- /dev/null +++ b/src/components/Layout.tsx @@ -0,0 +1,35 @@ +import Global from "~/lib/Global"; +import Navigation from "./Navigation"; + +interface LayoutProps { + children: JSX.Element | JSX.Element[]; +} + +export default function Layout({ children }: LayoutProps) { + return ( +
+ +
Header
+ + {children} +
+ ); +} diff --git a/src/components/Navigation.tsx b/src/components/Navigation.tsx new file mode 100644 index 0000000..d880f42 --- /dev/null +++ b/src/components/Navigation.tsx @@ -0,0 +1,31 @@ +interface NavigationItem { + name: string; + href: string; +} + +const items: NavigationItem[] = [ + { name: "Home", href: "/" }, + { name: "About", href: "/about" }, +]; + +export default function Navigation() { + return ( + + ); +} diff --git a/src/css.d.ts b/src/css.d.ts new file mode 100644 index 0000000..f3d8b55 --- /dev/null +++ b/src/css.d.ts @@ -0,0 +1,9 @@ +declare module "*.css" { + const content: string; + export default content; +} + +declare module "*.html" { + const content: string; + export default content; +} diff --git a/src/index.tsx b/src/index.tsx new file mode 100644 index 0000000..bfedebe --- /dev/null +++ b/src/index.tsx @@ -0,0 +1,61 @@ +import { fillTemplate, render } from "./lib/fast-web"; +import template from "./template.html" with { type: "text" }; +import theme from "./theme.css" with { type: "text" }; +import staticDir from "serve-static-bun"; + +const router = new Bun.FileSystemRouter({ + style: "nextjs", + dir: __dirname + "/pages", +}); + +const staticPublic = staticDir("./public"); + +const glob = new Bun.Glob(__dirname + "/scripts/*"); + +const server = Bun.serve({ + port: 8080, + fetch: async (req): Promise => { + if (req.url.endsWith("ws")) { + if (server.upgrade(req)) return new Response("ok"); + } + + const match = router.match(req); + if (!match) return staticPublic(req); + const Comp = (await import(__dirname + "/pages/" + match?.pathname)) + .default; + const renderResult = render(, [theme]); + + const systemScripts = await Bun.build({ + entrypoints: [...glob.scanSync()], + minify: true, + }); + const scripts = await Promise.all( + systemScripts.outputs.map( + async (script) => ``, + ), + ); + + return new Response( + fillTemplate(template, { + head: renderResult.head + scripts, + body: renderResult.html, + }), + { + headers: { + "content-type": "text/html", + }, + }, + ); + }, + websocket: { + message: () => {}, + open: async (ws) => { + console.log("connected"); + ws.subscribe("reload"); + }, + }, +}); + +server.publish("reload", "reload"); + +console.log("Listening on http://localhost:8080"); diff --git a/src/jsx.d.ts b/src/jsx.d.ts new file mode 100644 index 0000000..8691360 --- /dev/null +++ b/src/jsx.d.ts @@ -0,0 +1,66 @@ +namespace JSX { + interface FC { + (props: any): JSX.Element | string | null; + } + type Children = + | JSX.Element + | (string | JSX.Element | JSX.Element[])[] + | string + | null + | undefined; + type CSSTypeProperties = import("csstype").Properties; + type CSSProperties = import("csstype").Properties & { + marginX?: CSSTypeProperties["marginLeft"]; + marginY?: CSSTypeProperties["marginTop"]; + paddingX?: CSSTypeProperties["paddingLeft"]; + paddingY?: CSSTypeProperties["paddingTop"]; + }; + type BaseElementPropsWithoutChildren = { + className?: string; + style?: CSSProperties; + } & Partial; + type BaseElementProps = BaseElementPropsWithoutChildren & { + children?: JSX.Children; + }; + interface IntrinsicElements { + a: BaseElementProps & { + href?: string; + target?: HTMLAnchorElement["target"]; + }; + + // Void IntrinsicElements + // https://github.com/wooorm/html-void-elements + area: BaseElementPropsWithoutChildren; + base: BaseElementPropsWithoutChildren; + basefont: BaseElementPropsWithoutChildren; + bgsound: BaseElementPropsWithoutChildren; + br: BaseElementPropsWithoutChildren; + col: BaseElementPropsWithoutChildren; + command: BaseElementPropsWithoutChildren; + embed: BaseElementPropsWithoutChildren; + frame: BaseElementPropsWithoutChildren; + hr: BaseElementPropsWithoutChildren; + image: BaseElementPropsWithoutChildren; + img: BaseElementPropsWithoutChildren; + input: BaseElementPropsWithoutChildren; + keygen: BaseElementPropsWithoutChildren; + link: BaseElementPropsWithoutChildren; + meta: BaseElementPropsWithoutChildren; + param: BaseElementPropsWithoutChildren; + source: BaseElementPropsWithoutChildren; + track: BaseElementPropsWithoutChildren; + wbr: BaseElementPropsWithoutChildren; + [tagName: string]: BaseElementProps; + } + interface Element { + $$typeof: Symbol; + type: string | FC | null; + key?: string; + ref?: string; + children?: JSX.Children; + props: any; + } + interface ElementChildrenAttribute { + children: {}; + } +} diff --git a/src/lib/Global.tsx b/src/lib/Global.tsx new file mode 100644 index 0000000..c9b5de7 --- /dev/null +++ b/src/lib/Global.tsx @@ -0,0 +1,20 @@ +import { getStyleRules } from "~/system/style-rules"; +import { pushStyle } from "./fast-web"; + +interface GlobalProps { + css?: Record; +} + +export default function Global({ css = {} }: GlobalProps) { + const stylesArray = Object.entries(css).map<[string, string[]]>( + ([key, value]) => { + return [key, getStyleRules(value)]; + }, + ); + + stylesArray.forEach(([key, value]) => { + pushStyle(`${key} {${value.join(" ")}}`); + }); + + return null; +} diff --git a/src/lib/fast-web.ts b/src/lib/fast-web.ts new file mode 100644 index 0000000..ee5e806 --- /dev/null +++ b/src/lib/fast-web.ts @@ -0,0 +1,86 @@ +import { camelToKebab, renderStyle } from "~/system/style-rules"; +import { transform } from "lightningcss"; +import reset from "./reset.css" with { type: "text" }; + +const renderChildren = (elements: JSX.Children): string => { + if (Array.isArray(elements)) { + return elements.map((element) => renderChildren(element)).join(""); + } + if (typeof elements === "string") { + return elements; + } + return renderElement(elements); +}; + +let styles: string[] = []; + +export const pushStyle = (style: string) => { + styles.push(style); +}; + +const renderElement = ( + element: JSX.Element | string | null | undefined, +): string => { + if (!element) { + return ""; + } + if (typeof element === "string") { + return element; + } + if (element.$$typeof === Symbol.for("fast.fragment")) { + return renderChildren(element.children); + } + if (typeof element.type === "string") { + let { className, ...otherProps } = element.props; + if ("style" in element.props) { + const res = renderStyle(element.props.style); + styles.push(res.css); + className = className ? `${className} ${res.className}` : res.className; + } + const props = { ...otherProps, class: className }; + const attrs = Object.entries(props).map(([key, value]) => { + if (key === "children") { + return ""; + } + if (key === "style") { + return ""; + } + if (!value) { + return ""; + } + return ` ${camelToKebab(key)}="${value}"`; + }); + return `<${element.type}${attrs.join("")}>${element.children ? renderChildren(element.children) : ""}`; + } + if (typeof element.type === "function") { + return renderElement( + element.type({ ...element.props, children: element.children }), + ); + } + return ""; +}; + +export const render = ( + element: JSX.Element | string | null, + extraCss: string[] = [], +) => { + styles = [reset, ...extraCss]; + const html = renderElement(element); + const encoder = new TextEncoder(); + const css = transform({ + code: encoder.encode(styles.join("\n")), + minify: true, + filename: "render-style.ts", + }).code; + const head = ``; + return { html, head }; +}; + +export const fillTemplate = ( + template: string, + data: Record, +) => { + return Object.entries(data).reduce((acc, [key, value]) => { + return acc.replace(``, value); + }, template); +}; diff --git a/src/lib/reset.css b/src/lib/reset.css new file mode 100644 index 0000000..6ca3d16 --- /dev/null +++ b/src/lib/reset.css @@ -0,0 +1,42 @@ +@layer reset, base, utilities; + +@layer reset { + /* 1. Use a more-intuitive box-sizing model */ + *, *::before, *::after { + box-sizing: border-box; + } + /* 2. Remove default margin */ + * { + margin: 0; + } + body { + /* 3. Add accessible line-height */ + line-height: 1.5; + /* 4. Improve text rendering */ + -webkit-font-smoothing: antialiased; + } + /* 5. Improve media defaults */ + img, picture, video, canvas, svg { + display: block; + max-width: 100%; + } + /* 6. Inherit fonts for form controls */ + input, button, textarea, select { + font: inherit; + } + /* 7. Avoid text overflows */ + p, h1, h2, h3, h4, h5, h6 { + overflow-wrap: break-word; + } + /* 8. Improve line wrapping */ + p { + text-wrap: pretty; + } + h1, h2, h3, h4, h5, h6 { + text-wrap: balance; + } + a { + color: inherit; + text-decoration: none; + } +} diff --git a/src/pages/index.tsx b/src/pages/index.tsx new file mode 100644 index 0000000..e468b98 --- /dev/null +++ b/src/pages/index.tsx @@ -0,0 +1,9 @@ +import Layout from "~/components/Layout"; + +export default function Index() { + return ( + +
Hello World
+
+ ); +} diff --git a/src/runtime/jsx-dev-runtime.ts b/src/runtime/jsx-dev-runtime.ts new file mode 100644 index 0000000..1e39ca3 --- /dev/null +++ b/src/runtime/jsx-dev-runtime.ts @@ -0,0 +1,3 @@ +import { jsx, Fragment } from "./jsx-runtime"; +export const jsxDEV = jsx; +export { jsx, Fragment }; diff --git a/src/runtime/jsx-runtime.ts b/src/runtime/jsx-runtime.ts new file mode 100644 index 0000000..f3538d8 --- /dev/null +++ b/src/runtime/jsx-runtime.ts @@ -0,0 +1,25 @@ +export type FC = (props: any) => JSX.Element | null | string; + +export const jsx = function (type: string | FC, fullProps: any): JSX.Element { + const { children, ...props } = fullProps; + return { + $$typeof: Symbol.for("fast.element"), + type, + props, + key: props.key, + ref: props.ref, + children, + }; +}; + +export const Fragment = function (fullProps: any): JSX.Element { + const { children, ...props } = fullProps; + return { + $$typeof: Symbol.for("fast.fragment"), + type: null, + props, + key: props.key, + ref: props.ref, + children, + }; +}; diff --git a/src/scripts/hmr.ts b/src/scripts/hmr.ts new file mode 100644 index 0000000..d1995ba --- /dev/null +++ b/src/scripts/hmr.ts @@ -0,0 +1,15 @@ +interface DevWindow extends Window { + devListening?: boolean; +} + +declare const window: DevWindow; + +if (!window.devListening) { + const ws = new WebSocket("ws://localhost:8080/ws"); + ws.addEventListener("message", () => { + fetch(window.location.href).then(async (res) => { + window.document.documentElement.innerHTML = await res.text(); + }); + }); + window.devListening = true; +} diff --git a/src/system/css-utils.ts b/src/system/css-utils.ts new file mode 100644 index 0000000..e69de29 diff --git a/src/system/style-rules.ts b/src/system/style-rules.ts new file mode 100644 index 0000000..8b71426 --- /dev/null +++ b/src/system/style-rules.ts @@ -0,0 +1,55 @@ +import { getCategory, shorthand } from "./token-categories"; + +export const camelToKebab = (str: string) => { + return str.replace(/([a-z0-9]|(?=[A-Z]))([A-Z])/g, "$1-$2").toLowerCase(); +}; + +export const getStyleRules = (style: JSX.CSSProperties) => { + const styles = Object.entries(style).map(([key, value]) => { + return { + key, + value, + }; + }); + const rules = []; + while (styles.length) { + const { key, value } = styles.shift()!; + if (key in shorthand) { + const shorthandRules = shorthand[key as keyof typeof shorthand](value); + styles.unshift(...shorthandRules); + continue; + } + + const kKey = camelToKebab(key); + if (typeof value === "number") { + rules.push(`${kKey}: ${value}px;`); + } else if (typeof value === "string") { + const match = value.match(/\$([a-zA-Z0-9\.\-]+)/g); + if (match) { + const category = getCategory(key); + const replaceValue = match.reduce((v, m) => { + return v.replace( + m, + `var(--${category}${m.replaceAll("$", "").replaceAll(".", "-")})`, + ); + }, value); + rules.push(`${kKey}: ${replaceValue};`); + } else { + rules.push(`${kKey}: ${value};`); + } + } else { + rules.push(`${kKey}: ${value.join(" ")};`); + } + } + return rules; +}; + +export const renderStyle = (style: JSX.CSSProperties) => { + const rules = getStyleRules(style); + const sortedRules = rules.sort(); + const rulesString = sortedRules.join(" "); + const hash = Bun.hash(rulesString); + const className = `style-${hash.toString(36)}`; + const css = `.${className} {${rulesString}}`; + return { className, css }; +}; diff --git a/src/system/token-categories.ts b/src/system/token-categories.ts new file mode 100644 index 0000000..9019997 --- /dev/null +++ b/src/system/token-categories.ts @@ -0,0 +1,73 @@ +const tokenTypes = ["color", "space", "font"] as const; +type TokenType = (typeof tokenTypes)[number]; + +export const shorthand = { + marginX: (value: string) => [ + { + key: "marginLeft", + value, + }, + { + key: "marginRight", + value, + }, + ], + marginY: (value: string) => [ + { + key: "marginTop", + value, + }, + { + key: "marginBottom", + value, + }, + ], + paddingX: (value: string) => [ + { + key: "paddingLeft", + value, + }, + { + key: "paddingRight", + value, + }, + ], + paddingY: (value: string) => [ + { + key: "paddingTop", + value, + }, + { + key: "paddingBottom", + value, + }, + ], +}; + +export const categoryMap = { + color: "color", + backgroundColor: "color", + borderColor: "color", + margin: "space", + marginTop: "space", + marginBottom: "space", + marginLeft: "space", + marginRight: "space", + marginX: "space", + marginY: "space", + padding: "space", + paddingTop: "space", + paddingBottom: "space", + paddingLeft: "space", + paddingRight: "space", + paddingX: "space", + paddingY: "space", + gap: "space", + fontFamily: "font", +} as const satisfies Partial>; + +export const getCategory = (value: string) => { + return value in categoryMap + ? categoryMap[value as keyof typeof categoryMap] + "-" + : ""; +}; diff --git a/src/template.html b/src/template.html new file mode 100644 index 0000000..cc5ff68 --- /dev/null +++ b/src/template.html @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/src/theme.css b/src/theme.css new file mode 100644 index 0000000..0a66399 --- /dev/null +++ b/src/theme.css @@ -0,0 +1,284 @@ +@font-face { + font-family: "Rubik"; + src: url("/assets/Rubik.ttf"); + font-weight: 100 1000; +} + +:root { + /* Color tokens based pm tailwindcss */ + --color-red-50: oklch(0.971 0.013 17.38); + --color-red-100: oklch(0.936 0.032 17.717); + --color-red-200: oklch(0.885 0.062 18.334); + --color-red-300: oklch(0.808 0.114 19.571); + --color-red-400: oklch(0.704 0.191 22.216); + --color-red-500: oklch(0.637 0.237 25.331); + --color-red-600: oklch(0.577 0.245 27.325); + --color-red-700: oklch(0.505 0.213 27.518); + --color-red-800: oklch(0.444 0.177 26.899); + --color-red-900: oklch(0.396 0.141 25.723); + --color-red-950: oklch(0.258 0.092 26.042); + --color-orange-50: oklch(0.98 0.016 73.684); + --color-orange-100: oklch(0.954 0.038 75.164); + --color-orange-200: oklch(0.901 0.076 70.697); + --color-orange-300: oklch(0.837 0.128 66.29); + --color-orange-400: oklch(0.75 0.183 55.934); + --color-orange-500: oklch(0.705 0.213 47.604); + --color-orange-600: oklch(0.646 0.222 41.116); + --color-orange-700: oklch(0.553 0.195 38.402); + --color-orange-800: oklch(0.47 0.157 37.304); + --color-orange-900: oklch(0.408 0.123 38.172); + --color-orange-950: oklch(0.266 0.079 36.259); + --color-amber-50: oklch(0.987 0.022 95.277); + --color-amber-100: oklch(0.962 0.059 95.617); + --color-amber-200: oklch(0.924 0.12 95.746); + --color-amber-300: oklch(0.879 0.169 91.605); + --color-amber-400: oklch(0.828 0.189 84.429); + --color-amber-500: oklch(0.769 0.188 70.08); + --color-amber-600: oklch(0.666 0.179 58.318); + --color-amber-700: oklch(0.555 0.163 48.998); + --color-amber-800: oklch(0.473 0.137 46.201); + --color-amber-900: oklch(0.414 0.112 45.904); + --color-amber-950: oklch(0.279 0.077 45.635); + --color-yellow-50: oklch(0.987 0.026 102.212); + --color-yellow-100: oklch(0.973 0.071 103.193); + --color-yellow-200: oklch(0.945 0.129 101.54); + --color-yellow-300: oklch(0.905 0.182 98.111); + --color-yellow-400: oklch(0.852 0.199 91.936); + --color-yellow-500: oklch(0.795 0.184 86.047); + --color-yellow-600: oklch(0.681 0.162 75.834); + --color-yellow-700: oklch(0.554 0.135 66.442); + --color-yellow-800: oklch(0.476 0.114 61.907); + --color-yellow-900: oklch(0.421 0.095 57.708); + --color-yellow-950: oklch(0.286 0.066 53.813); + --color-lime-50: oklch(0.986 0.031 120.757); + --color-lime-100: oklch(0.967 0.067 122.328); + --color-lime-200: oklch(0.938 0.127 124.321); + --color-lime-300: oklch(0.897 0.196 126.665); + --color-lime-400: oklch(0.841 0.238 128.85); + --color-lime-500: oklch(0.768 0.233 130.85); + --color-lime-600: oklch(0.648 0.2 131.684); + --color-lime-700: oklch(0.532 0.157 131.589); + --color-lime-800: oklch(0.453 0.124 130.933); + --color-lime-900: oklch(0.405 0.101 131.063); + --color-lime-950: oklch(0.274 0.072 132.109); + --color-green-50: oklch(0.982 0.018 155.826); + --color-green-100: oklch(0.962 0.044 156.743); + --color-green-200: oklch(0.925 0.084 155.995); + --color-green-300: oklch(0.871 0.15 154.449); + --color-green-400: oklch(0.792 0.209 151.711); + --color-green-500: oklch(0.723 0.219 149.579); + --color-green-600: oklch(0.627 0.194 149.214); + --color-green-700: oklch(0.527 0.154 150.069); + --color-green-800: oklch(0.448 0.119 151.328); + --color-green-900: oklch(0.393 0.095 152.535); + --color-green-950: oklch(0.266 0.065 152.934); + --color-emerald-50: oklch(0.979 0.021 166.113); + --color-emerald-100: oklch(0.95 0.052 163.051); + --color-emerald-200: oklch(0.905 0.093 164.15); + --color-emerald-300: oklch(0.845 0.143 164.978); + --color-emerald-400: oklch(0.765 0.177 163.223); + --color-emerald-500: oklch(0.696 0.17 162.48); + --color-emerald-600: oklch(0.596 0.145 163.225); + --color-emerald-700: oklch(0.508 0.118 165.612); + --color-emerald-800: oklch(0.432 0.095 166.913); + --color-emerald-900: oklch(0.378 0.077 168.94); + --color-emerald-950: oklch(0.262 0.051 172.552); + --color-teal-50: oklch(0.984 0.014 180.72); + --color-teal-100: oklch(0.953 0.051 180.801); + --color-teal-200: oklch(0.91 0.096 180.426); + --color-teal-300: oklch(0.855 0.138 181.071); + --color-teal-400: oklch(0.777 0.152 181.912); + --color-teal-500: oklch(0.704 0.14 182.503); + --color-teal-600: oklch(0.6 0.118 184.704); + --color-teal-700: oklch(0.511 0.096 186.391); + --color-teal-800: oklch(0.437 0.078 188.216); + --color-teal-900: oklch(0.386 0.063 188.416); + --color-teal-950: oklch(0.277 0.046 192.524); + --color-cyan-50: oklch(0.984 0.019 200.873); + --color-cyan-100: oklch(0.956 0.045 203.388); + --color-cyan-200: oklch(0.917 0.08 205.041); + --color-cyan-300: oklch(0.865 0.127 207.078); + --color-cyan-400: oklch(0.789 0.154 211.53); + --color-cyan-500: oklch(0.715 0.143 215.221); + --color-cyan-600: oklch(0.609 0.126 221.723); + --color-cyan-700: oklch(0.52 0.105 223.128); + --color-cyan-800: oklch(0.45 0.085 224.283); + --color-cyan-900: oklch(0.398 0.07 227.392); + --color-cyan-950: oklch(0.302 0.056 229.695); + --color-sky-50: oklch(0.977 0.013 236.62); + --color-sky-100: oklch(0.951 0.026 236.824); + --color-sky-200: oklch(0.901 0.058 230.902); + --color-sky-300: oklch(0.828 0.111 230.318); + --color-sky-400: oklch(0.746 0.16 232.661); + --color-sky-500: oklch(0.685 0.169 237.323); + --color-sky-600: oklch(0.588 0.158 241.966); + --color-sky-700: oklch(0.5 0.134 242.749); + --color-sky-800: oklch(0.443 0.11 240.79); + --color-sky-900: oklch(0.391 0.09 240.876); + --color-sky-950: oklch(0.293 0.066 243.157); + --color-blue-50: oklch(0.97 0.014 254.604); + --color-blue-100: oklch(0.932 0.032 255.585); + --color-blue-200: oklch(0.882 0.059 254.128); + --color-blue-300: oklch(0.809 0.105 251.813); + --color-blue-400: oklch(0.707 0.165 254.624); + --color-blue-500: oklch(0.623 0.214 259.815); + --color-blue-600: oklch(0.546 0.245 262.881); + --color-blue-700: oklch(0.488 0.243 264.376); + --color-blue-800: oklch(0.424 0.199 265.638); + --color-blue-900: oklch(0.379 0.146 265.522); + --color-blue-950: oklch(0.282 0.091 267.935); + --color-indigo-50: oklch(0.962 0.018 272.314); + --color-indigo-100: oklch(0.93 0.034 272.788); + --color-indigo-200: oklch(0.87 0.065 274.039); + --color-indigo-300: oklch(0.785 0.115 274.713); + --color-indigo-400: oklch(0.673 0.182 276.935); + --color-indigo-500: oklch(0.585 0.233 277.117); + --color-indigo-600: oklch(0.511 0.262 276.966); + --color-indigo-700: oklch(0.457 0.24 277.023); + --color-indigo-800: oklch(0.398 0.195 277.366); + --color-indigo-900: oklch(0.359 0.144 278.697); + --color-indigo-950: oklch(0.257 0.09 281.288); + --color-violet-50: oklch(0.969 0.016 293.756); + --color-violet-100: oklch(0.943 0.029 294.588); + --color-violet-200: oklch(0.894 0.057 293.283); + --color-violet-300: oklch(0.811 0.111 293.571); + --color-violet-400: oklch(0.702 0.183 293.541); + --color-violet-500: oklch(0.606 0.25 292.717); + --color-violet-600: oklch(0.541 0.281 293.009); + --color-violet-700: oklch(0.491 0.27 292.581); + --color-violet-800: oklch(0.432 0.232 292.759); + --color-violet-900: oklch(0.38 0.189 293.745); + --color-violet-950: oklch(0.283 0.141 291.089); + --color-purple-50: oklch(0.977 0.014 308.299); + --color-purple-100: oklch(0.946 0.033 307.174); + --color-purple-200: oklch(0.902 0.063 306.703); + --color-purple-300: oklch(0.827 0.119 306.383); + --color-purple-400: oklch(0.714 0.203 305.504); + --color-purple-500: oklch(0.627 0.265 303.9); + --color-purple-600: oklch(0.558 0.288 302.321); + --color-purple-700: oklch(0.496 0.265 301.924); + --color-purple-800: oklch(0.438 0.218 303.724); + --color-purple-900: oklch(0.381 0.176 304.987); + --color-purple-950: oklch(0.291 0.149 302.717); + --color-fuchsia-50: oklch(0.977 0.017 320.058); + --color-fuchsia-100: oklch(0.952 0.037 318.852); + --color-fuchsia-200: oklch(0.903 0.076 319.62); + --color-fuchsia-300: oklch(0.833 0.145 321.434); + --color-fuchsia-400: oklch(0.74 0.238 322.16); + --color-fuchsia-500: oklch(0.667 0.295 322.15); + --color-fuchsia-600: oklch(0.591 0.293 322.896); + --color-fuchsia-700: oklch(0.518 0.253 323.949); + --color-fuchsia-800: oklch(0.452 0.211 324.591); + --color-fuchsia-900: oklch(0.401 0.17 325.612); + --color-fuchsia-950: oklch(0.293 0.136 325.661); + --color-pink-50: oklch(0.971 0.014 343.198); + --color-pink-100: oklch(0.948 0.028 342.258); + --color-pink-200: oklch(0.899 0.061 343.231); + --color-pink-300: oklch(0.823 0.12 346.018); + --color-pink-400: oklch(0.718 0.202 349.761); + --color-pink-500: oklch(0.656 0.241 354.308); + --color-pink-600: oklch(0.592 0.249 0.584); + --color-pink-700: oklch(0.525 0.223 3.958); + --color-pink-800: oklch(0.459 0.187 3.815); + --color-pink-900: oklch(0.408 0.153 2.432); + --color-pink-950: oklch(0.284 0.109 3.907); + --color-rose-50: oklch(0.969 0.015 12.422); + --color-rose-100: oklch(0.941 0.03 12.58); + --color-rose-200: oklch(0.892 0.058 10.001); + --color-rose-300: oklch(0.81 0.117 11.638); + --color-rose-400: oklch(0.712 0.194 13.428); + --color-rose-500: oklch(0.645 0.246 16.439); + --color-rose-600: oklch(0.586 0.253 17.585); + --color-rose-700: oklch(0.514 0.222 16.935); + --color-rose-800: oklch(0.455 0.188 13.697); + --color-rose-900: oklch(0.41 0.159 10.272); + --color-rose-950: oklch(0.271 0.105 12.094); + --color-slate-50: oklch(0.984 0.003 247.858); + --color-slate-100: oklch(0.968 0.007 247.896); + --color-slate-200: oklch(0.929 0.013 255.508); + --color-slate-300: oklch(0.869 0.022 252.894); + --color-slate-400: oklch(0.704 0.04 256.788); + --color-slate-500: oklch(0.554 0.046 257.417); + --color-slate-600: oklch(0.446 0.043 257.281); + --color-slate-700: oklch(0.372 0.044 257.287); + --color-slate-800: oklch(0.279 0.041 260.031); + --color-slate-900: oklch(0.208 0.042 265.755); + --color-slate-950: oklch(0.129 0.042 264.695); + --color-gray-50: oklch(0.985 0.002 247.839); + --color-gray-100: oklch(0.967 0.003 264.542); + --color-gray-200: oklch(0.928 0.006 264.531); + --color-gray-300: oklch(0.872 0.01 258.338); + --color-gray-400: oklch(0.707 0.022 261.325); + --color-gray-500: oklch(0.551 0.027 264.364); + --color-gray-600: oklch(0.446 0.03 256.802); + --color-gray-700: oklch(0.373 0.034 259.733); + --color-gray-800: oklch(0.278 0.033 256.848); + --color-gray-900: oklch(0.21 0.034 264.665); + --color-gray-950: oklch(0.13 0.028 261.692); + --color-zinc-50: oklch(0.985 0 0); + --color-zinc-100: oklch(0.967 0.001 286.375); + --color-zinc-200: oklch(0.92 0.004 286.32); + --color-zinc-300: oklch(0.871 0.006 286.286); + --color-zinc-400: oklch(0.705 0.015 286.067); + --color-zinc-500: oklch(0.552 0.016 285.938); + --color-zinc-600: oklch(0.442 0.017 285.786); + --color-zinc-700: oklch(0.37 0.013 285.805); + --color-zinc-800: oklch(0.274 0.006 286.033); + --color-zinc-900: oklch(0.21 0.006 285.885); + --color-zinc-950: oklch(0.141 0.005 285.823); + --color-neutral-50: oklch(0.985 0 0); + --color-neutral-100: oklch(0.97 0 0); + --color-neutral-200: oklch(0.922 0 0); + --color-neutral-300: oklch(0.87 0 0); + --color-neutral-400: oklch(0.708 0 0); + --color-neutral-500: oklch(0.556 0 0); + --color-neutral-600: oklch(0.439 0 0); + --color-neutral-700: oklch(0.371 0 0); + --color-neutral-800: oklch(0.269 0 0); + --color-neutral-900: oklch(0.205 0 0); + --color-neutral-950: oklch(0.145 0 0); + --color-stone-50: oklch(0.985 0.001 106.423); + --color-stone-100: oklch(0.97 0.001 106.424); + --color-stone-200: oklch(0.923 0.003 48.717); + --color-stone-300: oklch(0.869 0.005 56.366); + --color-stone-400: oklch(0.709 0.01 56.259); + --color-stone-500: oklch(0.553 0.013 58.071); + --color-stone-600: oklch(0.444 0.011 73.639); + --color-stone-700: oklch(0.374 0.01 67.558); + --color-stone-800: oklch(0.268 0.007 34.298); + --color-stone-900: oklch(0.216 0.006 56.043); + --color-stone-950: oklch(0.147 0.004 49.25); + --color-black: #000; + --color-white: #fff; + + --space-1: 0.25rem; + --space-2: 0.5rem; + --space-3: 0.75rem; + --space-4: 1rem; + --space-5: 1.25rem; + --space-6: 1.5rem; + --space-7: 1.75rem; + --space-8: 2rem; + --space-9: 2.25rem; + --space-10: 2.5rem; + --space-11: 2.75rem; + --space-12: 3rem; + --space-14: 3.5rem; + --space-16: 4rem; + --space-20: 5rem; + --space-24: 6rem; + --space-28: 7rem; + --space-32: 8rem; + --space-36: 9rem; + --space-40: 10rem; + --space-44: 11rem; + --space-48: 12rem; + --space-52: 13rem; + --space-56: 14rem; + --space-60: 15rem; + --space-64: 16rem; + --space-72: 18rem; + --space-80: 20rem; + + --font-sans: "Rubik", sans-serif; +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..c8f6867 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,31 @@ +{ + "compilerOptions": { + // Enable latest features + "lib": ["ESNext", "DOM"], + "target": "ESNext", + "module": "ESNext", + "moduleDetection": "force", + "jsx": "react-jsx", + "jsxImportSource": "~/runtime", + "rootDir": "./src", + "allowJs": true, + // Bundler mode + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "verbatimModuleSyntax": true, + "noEmit": true, + + // Best practices + "strict": true, + "skipLibCheck": true, + "noFallthroughCasesInSwitch": true, + + // Some stricter flags (disabled by default) + "noUnusedLocals": false, + "noUnusedParameters": false, + "noPropertyAccessFromIndexSignature": false, + "paths": { + "~/*": ["./src/*"] + } + } +}