mirror of https://github.com/acid-info/lsd.git
chore: initial Commit
This commit is contained in:
commit
5204ceff92
|
@ -0,0 +1 @@
|
||||||
|
node_modules/
|
|
@ -0,0 +1,4 @@
|
||||||
|
#!/usr/bin/env sh
|
||||||
|
. "$(dirname -- "$0")/_/husky.sh"
|
||||||
|
|
||||||
|
npx --no -- commitlint --edit ${1}
|
|
@ -0,0 +1,4 @@
|
||||||
|
#!/usr/bin/env sh
|
||||||
|
. "$(dirname -- "$0")/_/husky.sh"
|
||||||
|
|
||||||
|
npx lint-staged
|
|
@ -0,0 +1,3 @@
|
||||||
|
.next
|
||||||
|
coverage
|
||||||
|
dist
|
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"tabWidth": 2,
|
||||||
|
"semi": false,
|
||||||
|
"singleQuote": true,
|
||||||
|
"trailingComma": "all"
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
{
|
||||||
|
"extends": "next/core-web-vitals"
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||||
|
|
||||||
|
# dependencies
|
||||||
|
/node_modules
|
||||||
|
/.pnp
|
||||||
|
.pnp.js
|
||||||
|
|
||||||
|
# testing
|
||||||
|
/coverage
|
||||||
|
|
||||||
|
# next.js
|
||||||
|
/.next/
|
||||||
|
/out/
|
||||||
|
|
||||||
|
# production
|
||||||
|
/build
|
||||||
|
|
||||||
|
# misc
|
||||||
|
.DS_Store
|
||||||
|
*.pem
|
||||||
|
|
||||||
|
# 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
|
|
@ -0,0 +1,38 @@
|
||||||
|
This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).
|
||||||
|
|
||||||
|
## Getting Started
|
||||||
|
|
||||||
|
First, run the development server:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run dev
|
||||||
|
# or
|
||||||
|
yarn dev
|
||||||
|
# or
|
||||||
|
pnpm dev
|
||||||
|
```
|
||||||
|
|
||||||
|
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
|
||||||
|
|
||||||
|
You can start editing the page by modifying `pages/index.tsx`. The page auto-updates as you edit the file.
|
||||||
|
|
||||||
|
[API routes](https://nextjs.org/docs/api-routes/introduction) can be accessed on [http://localhost:3000/api/hello](http://localhost:3000/api/hello). This endpoint can be edited in `pages/api/hello.ts`.
|
||||||
|
|
||||||
|
The `pages/api` directory is mapped to `/api/*`. Files in this directory are treated as [API routes](https://nextjs.org/docs/api-routes/introduction) instead of React pages.
|
||||||
|
|
||||||
|
This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font.
|
||||||
|
|
||||||
|
## Learn More
|
||||||
|
|
||||||
|
To learn more about Next.js, take a look at the following resources:
|
||||||
|
|
||||||
|
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
|
||||||
|
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
|
||||||
|
|
||||||
|
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!
|
||||||
|
|
||||||
|
## Deploy on Vercel
|
||||||
|
|
||||||
|
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
|
||||||
|
|
||||||
|
Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.
|
|
@ -0,0 +1,6 @@
|
||||||
|
/** @type {import('next').NextConfig} */
|
||||||
|
const nextConfig = {
|
||||||
|
reactStrictMode: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = nextConfig
|
|
@ -0,0 +1,29 @@
|
||||||
|
{
|
||||||
|
"name": "@acid-info/lsd-website",
|
||||||
|
"version": "0.0.0",
|
||||||
|
"private": true,
|
||||||
|
"scripts": {
|
||||||
|
"dev": "next dev",
|
||||||
|
"build": "next build",
|
||||||
|
"start": "next start",
|
||||||
|
"lint": "next lint"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@acid-info/lsd-react": "*",
|
||||||
|
"@emotion/react": "^11.10.5",
|
||||||
|
"@emotion/styled": "^11.10.5",
|
||||||
|
"@next/font": "13.1.6",
|
||||||
|
"@types/node": "18.11.18",
|
||||||
|
"@types/react": "18.0.27",
|
||||||
|
"@types/react-dom": "18.0.10",
|
||||||
|
"eslint": "8.33.0",
|
||||||
|
"eslint-config-next": "13.1.6",
|
||||||
|
"next": "13.1.6",
|
||||||
|
"react": "18.2.0",
|
||||||
|
"react-dom": "18.2.0",
|
||||||
|
"typescript": "4.9.5"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"vite-plugin-dts": "^1.7.2"
|
||||||
|
}
|
||||||
|
}
|
Binary file not shown.
After Width: | Height: | Size: 25 KiB |
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 394 80"><path fill="#000" d="M262 0h68.5v12.7h-27.2v66.6h-13.6V12.7H262V0ZM149 0v12.7H94v20.4h44.3v12.6H94v21h55v12.6H80.5V0h68.7zm34.3 0h-17.8l63.8 79.4h17.9l-32-39.7 32-39.6h-17.9l-23 28.6-23-28.6zm18.3 56.7-9-11-27.1 33.7h17.8l18.3-22.7z"/><path fill="#000" d="M81 79.3 17 0H0v79.3h13.6V17l50.2 62.3H81Zm252.6-.4c-1 0-1.8-.4-2.5-1s-1.1-1.6-1.1-2.6.3-1.8 1-2.5 1.6-1 2.6-1 1.8.3 2.5 1a3.4 3.4 0 0 1 .6 4.3 3.7 3.7 0 0 1-3 1.8zm23.2-33.5h6v23.3c0 2.1-.4 4-1.3 5.5a9.1 9.1 0 0 1-3.8 3.5c-1.6.8-3.5 1.3-5.7 1.3-2 0-3.7-.4-5.3-1s-2.8-1.8-3.7-3.2c-.9-1.3-1.4-3-1.4-5h6c.1.8.3 1.6.7 2.2s1 1.2 1.6 1.5c.7.4 1.5.5 2.4.5 1 0 1.8-.2 2.4-.6a4 4 0 0 0 1.6-1.8c.3-.8.5-1.8.5-3V45.5zm30.9 9.1a4.4 4.4 0 0 0-2-3.3 7.5 7.5 0 0 0-4.3-1.1c-1.3 0-2.4.2-3.3.5-.9.4-1.6 1-2 1.6a3.5 3.5 0 0 0-.3 4c.3.5.7.9 1.3 1.2l1.8 1 2 .5 3.2.8c1.3.3 2.5.7 3.7 1.2a13 13 0 0 1 3.2 1.8 8.1 8.1 0 0 1 3 6.5c0 2-.5 3.7-1.5 5.1a10 10 0 0 1-4.4 3.5c-1.8.8-4.1 1.2-6.8 1.2-2.6 0-4.9-.4-6.8-1.2-2-.8-3.4-2-4.5-3.5a10 10 0 0 1-1.7-5.6h6a5 5 0 0 0 3.5 4.6c1 .4 2.2.6 3.4.6 1.3 0 2.5-.2 3.5-.6 1-.4 1.8-1 2.4-1.7a4 4 0 0 0 .8-2.4c0-.9-.2-1.6-.7-2.2a11 11 0 0 0-2.1-1.4l-3.2-1-3.8-1c-2.8-.7-5-1.7-6.6-3.2a7.2 7.2 0 0 1-2.4-5.7 8 8 0 0 1 1.7-5 10 10 0 0 1 4.3-3.5c2-.8 4-1.2 6.4-1.2 2.3 0 4.4.4 6.2 1.2 1.8.8 3.2 2 4.3 3.4 1 1.4 1.5 3 1.5 5h-5.8z"/></svg>
|
After Width: | Height: | Size: 1.3 KiB |
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="40" height="31" fill="none"><g opacity=".9"><path fill="url(#a)" d="M13 .4v29.3H7V6.3h-.2L0 10.5V5L7.2.4H13Z"/><path fill="url(#b)" d="M28.8 30.1c-2.2 0-4-.3-5.7-1-1.7-.8-3-1.8-4-3.1a7.7 7.7 0 0 1-1.4-4.6h6.2c0 .8.3 1.4.7 2 .4.5 1 .9 1.7 1.2.7.3 1.6.4 2.5.4 1 0 1.7-.2 2.5-.5.7-.3 1.3-.8 1.7-1.4.4-.6.6-1.2.6-2s-.2-1.5-.7-2.1c-.4-.6-1-1-1.8-1.4-.8-.4-1.8-.5-2.9-.5h-2.7v-4.6h2.7a6 6 0 0 0 2.5-.5 4 4 0 0 0 1.7-1.3c.4-.6.6-1.3.6-2a3.5 3.5 0 0 0-2-3.3 5.6 5.6 0 0 0-4.5 0 4 4 0 0 0-1.7 1.2c-.4.6-.6 1.2-.6 2h-6c0-1.7.6-3.2 1.5-4.5 1-1.3 2.2-2.3 3.8-3C25 .4 26.8 0 28.8 0s3.8.4 5.3 1.1c1.5.7 2.7 1.7 3.6 3a7.2 7.2 0 0 1 1.2 4.2c0 1.6-.5 3-1.5 4a7 7 0 0 1-4 2.2v.2c2.2.3 3.8 1 5 2.2a6.4 6.4 0 0 1 1.6 4.6c0 1.7-.5 3.1-1.4 4.4a9.7 9.7 0 0 1-4 3.1c-1.7.8-3.7 1.1-5.8 1.1Z"/></g><defs><linearGradient id="a" x1="20" x2="20" y1="0" y2="30.1" gradientUnits="userSpaceOnUse"><stop/><stop offset="1" stop-color="#3D3D3D"/></linearGradient><linearGradient id="b" x1="20" x2="20" y1="0" y2="30.1" gradientUnits="userSpaceOnUse"><stop/><stop offset="1" stop-color="#3D3D3D"/></linearGradient></defs></svg>
|
After Width: | Height: | Size: 1.1 KiB |
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 283 64"><path fill="black" d="M141 16c-11 0-19 7-19 18s9 18 20 18c7 0 13-3 16-7l-7-5c-2 3-6 4-9 4-5 0-9-3-10-7h28v-3c0-11-8-18-19-18zm-9 15c1-4 4-7 9-7s8 3 9 7h-18zm117-15c-11 0-19 7-19 18s9 18 20 18c6 0 12-3 16-7l-8-5c-2 3-5 4-8 4-5 0-9-3-11-7h28l1-3c0-11-8-18-19-18zm-10 15c2-4 5-7 10-7s8 3 9 7h-19zm-39 3c0 6 4 10 10 10 4 0 7-2 9-5l8 5c-3 5-9 8-17 8-11 0-19-7-19-18s8-18 19-18c8 0 14 3 17 8l-8 5c-2-3-5-5-9-5-6 0-10 4-10 10zm83-29v46h-9V5h9zM37 0l37 64H0L37 0zm92 5-27 48L74 5h10l18 30 17-30h10zm59 12v10l-3-1c-6 0-10 4-10 10v15h-9V17h9v9c0-5 6-9 13-9z"/></svg>
|
After Width: | Height: | Size: 629 B |
|
@ -0,0 +1,22 @@
|
||||||
|
import '@/styles/globals.css'
|
||||||
|
import { dark, light } from '@/theme'
|
||||||
|
import { Button, ThemeProvider } from '@acid-info/lsd-react'
|
||||||
|
import type { AppProps } from 'next/app'
|
||||||
|
import { useState } from 'react'
|
||||||
|
|
||||||
|
export default function App({ Component, pageProps }: AppProps) {
|
||||||
|
const [isDark, setIsDark] = useState(false)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ThemeProvider theme={isDark ? dark : light}>
|
||||||
|
<Button
|
||||||
|
onClick={() => {
|
||||||
|
setIsDark((v) => !v)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
switch
|
||||||
|
</Button>
|
||||||
|
<Component {...pageProps} />
|
||||||
|
</ThemeProvider>
|
||||||
|
)
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
import { Head, Html, Main, NextScript } from 'next/document'
|
||||||
|
|
||||||
|
export default function Document() {
|
||||||
|
return (
|
||||||
|
<Html lang="en">
|
||||||
|
<Head />
|
||||||
|
<body>
|
||||||
|
<Main />
|
||||||
|
<NextScript />
|
||||||
|
</body>
|
||||||
|
</Html>
|
||||||
|
)
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
|
||||||
|
import type { NextApiRequest, NextApiResponse } from 'next'
|
||||||
|
|
||||||
|
type Data = {
|
||||||
|
name: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function handler(
|
||||||
|
req: NextApiRequest,
|
||||||
|
res: NextApiResponse<Data>,
|
||||||
|
) {
|
||||||
|
res.status(200).json({ name: 'John Doe' })
|
||||||
|
}
|
|
@ -0,0 +1,57 @@
|
||||||
|
import styles from '@/styles/Home.module.css'
|
||||||
|
import { Button, useTheme } from '@acid-info/lsd-react'
|
||||||
|
import styled from '@emotion/styled'
|
||||||
|
import Head from 'next/head'
|
||||||
|
|
||||||
|
const StyledButton = styled(Button)`
|
||||||
|
&.${Button.classes.disabled} {
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
export default function Home() {
|
||||||
|
const theme = useTheme()
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Head>
|
||||||
|
<title>Create Next App</title>
|
||||||
|
<meta name="description" content="Generated by create next app" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
|
<link rel="icon" href="/favicon.ico" />
|
||||||
|
</Head>
|
||||||
|
<main className={styles.main}>
|
||||||
|
<div style={{ marginBottom: 50 }}>
|
||||||
|
<Button disabled>Simple Button</Button>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
width: 1000,
|
||||||
|
marginTop: 50,
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'column',
|
||||||
|
rowGap: 12,
|
||||||
|
alignItems: 'flex-start',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<StyledButton size="small" disabled>
|
||||||
|
Button
|
||||||
|
</StyledButton>
|
||||||
|
<StyledButton disabled size="medium">
|
||||||
|
Button
|
||||||
|
</StyledButton>
|
||||||
|
<StyledButton disabled size="large">
|
||||||
|
Button
|
||||||
|
</StyledButton>
|
||||||
|
|
||||||
|
<StyledButton size="small">Button</StyledButton>
|
||||||
|
<StyledButton size="medium">Button</StyledButton>
|
||||||
|
<StyledButton size="large">Button</StyledButton>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<pre>
|
||||||
|
<code>{theme.globalStyles.styles}</code>
|
||||||
|
</pre>
|
||||||
|
<style></style>
|
||||||
|
</main>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
|
@ -0,0 +1,279 @@
|
||||||
|
.main {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
padding: 6rem;
|
||||||
|
min-height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.description {
|
||||||
|
display: inherit;
|
||||||
|
justify-content: inherit;
|
||||||
|
align-items: inherit;
|
||||||
|
font-size: 0.85rem;
|
||||||
|
max-width: var(--max-width);
|
||||||
|
width: 100%;
|
||||||
|
z-index: 2;
|
||||||
|
font-family: var(--font-mono);
|
||||||
|
}
|
||||||
|
|
||||||
|
.description a {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.description p {
|
||||||
|
position: relative;
|
||||||
|
margin: 0;
|
||||||
|
padding: 1rem;
|
||||||
|
background-color: rgba(var(--callout-rgb), 0.5);
|
||||||
|
border: 1px solid rgba(var(--callout-border-rgb), 0.3);
|
||||||
|
border-radius: var(--border-radius);
|
||||||
|
}
|
||||||
|
|
||||||
|
.code {
|
||||||
|
font-weight: 700;
|
||||||
|
font-family: var(--font-mono);
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(4, minmax(25%, auto));
|
||||||
|
width: var(--max-width);
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card {
|
||||||
|
padding: 1rem 1.2rem;
|
||||||
|
border-radius: var(--border-radius);
|
||||||
|
background: rgba(var(--card-rgb), 0);
|
||||||
|
border: 1px solid rgba(var(--card-border-rgb), 0);
|
||||||
|
transition: background 200ms, border 200ms;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card span {
|
||||||
|
display: inline-block;
|
||||||
|
transition: transform 200ms;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card h2 {
|
||||||
|
font-weight: 600;
|
||||||
|
margin-bottom: 0.7rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card p {
|
||||||
|
margin: 0;
|
||||||
|
opacity: 0.6;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
line-height: 1.5;
|
||||||
|
max-width: 30ch;
|
||||||
|
}
|
||||||
|
|
||||||
|
.center {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
position: relative;
|
||||||
|
padding: 4rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.center::before {
|
||||||
|
background: var(--secondary-glow);
|
||||||
|
border-radius: 50%;
|
||||||
|
width: 480px;
|
||||||
|
height: 360px;
|
||||||
|
margin-left: -400px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.center::after {
|
||||||
|
background: var(--primary-glow);
|
||||||
|
width: 240px;
|
||||||
|
height: 180px;
|
||||||
|
z-index: -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.center::before,
|
||||||
|
.center::after {
|
||||||
|
content: '';
|
||||||
|
left: 50%;
|
||||||
|
position: absolute;
|
||||||
|
filter: blur(45px);
|
||||||
|
transform: translateZ(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo,
|
||||||
|
.thirteen {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.thirteen {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
width: 75px;
|
||||||
|
height: 75px;
|
||||||
|
padding: 25px 10px;
|
||||||
|
margin-left: 16px;
|
||||||
|
transform: translateZ(0);
|
||||||
|
border-radius: var(--border-radius);
|
||||||
|
overflow: hidden;
|
||||||
|
box-shadow: 0px 2px 8px -1px #0000001a;
|
||||||
|
}
|
||||||
|
|
||||||
|
.thirteen::before,
|
||||||
|
.thirteen::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
z-index: -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Conic Gradient Animation */
|
||||||
|
.thirteen::before {
|
||||||
|
animation: 6s rotate linear infinite;
|
||||||
|
width: 200%;
|
||||||
|
height: 200%;
|
||||||
|
background: var(--tile-border);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Inner Square */
|
||||||
|
.thirteen::after {
|
||||||
|
inset: 0;
|
||||||
|
padding: 1px;
|
||||||
|
border-radius: var(--border-radius);
|
||||||
|
background: linear-gradient(
|
||||||
|
to bottom right,
|
||||||
|
rgba(var(--tile-start-rgb), 1),
|
||||||
|
rgba(var(--tile-end-rgb), 1)
|
||||||
|
);
|
||||||
|
background-clip: content-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Enable hover only on non-touch devices */
|
||||||
|
@media (hover: hover) and (pointer: fine) {
|
||||||
|
.card:hover {
|
||||||
|
background: rgba(var(--card-rgb), 0.1);
|
||||||
|
border: 1px solid rgba(var(--card-border-rgb), 0.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
.card:hover span {
|
||||||
|
transform: translateX(4px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-reduced-motion) {
|
||||||
|
.thirteen::before {
|
||||||
|
animation: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card:hover span {
|
||||||
|
transform: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Mobile */
|
||||||
|
@media (max-width: 700px) {
|
||||||
|
.content {
|
||||||
|
padding: 4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
margin-bottom: 120px;
|
||||||
|
max-width: 320px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card {
|
||||||
|
padding: 1rem 2.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card h2 {
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.center {
|
||||||
|
padding: 8rem 0 6rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.center::before {
|
||||||
|
transform: none;
|
||||||
|
height: 300px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.description {
|
||||||
|
font-size: 0.8rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.description a {
|
||||||
|
padding: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.description p,
|
||||||
|
.description div {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
position: fixed;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.description p {
|
||||||
|
align-items: center;
|
||||||
|
inset: 0 0 auto;
|
||||||
|
padding: 2rem 1rem 1.4rem;
|
||||||
|
border-radius: 0;
|
||||||
|
border: none;
|
||||||
|
border-bottom: 1px solid rgba(var(--callout-border-rgb), 0.25);
|
||||||
|
background: linear-gradient(
|
||||||
|
to bottom,
|
||||||
|
rgba(var(--background-start-rgb), 1),
|
||||||
|
rgba(var(--callout-rgb), 0.5)
|
||||||
|
);
|
||||||
|
background-clip: padding-box;
|
||||||
|
backdrop-filter: blur(24px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.description div {
|
||||||
|
align-items: flex-end;
|
||||||
|
pointer-events: none;
|
||||||
|
inset: auto 0 0;
|
||||||
|
padding: 2rem;
|
||||||
|
height: 200px;
|
||||||
|
background: linear-gradient(
|
||||||
|
to bottom,
|
||||||
|
transparent 0%,
|
||||||
|
rgb(var(--background-end-rgb)) 40%
|
||||||
|
);
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Tablet and Smaller Desktop */
|
||||||
|
@media (min-width: 701px) and (max-width: 1120px) {
|
||||||
|
.grid {
|
||||||
|
grid-template-columns: repeat(2, 50%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-color-scheme: dark) {
|
||||||
|
.vercelLogo {
|
||||||
|
filter: invert(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo,
|
||||||
|
.thirteen img {
|
||||||
|
filter: invert(1) drop-shadow(0 0 0.3rem #ffffff70);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes rotate {
|
||||||
|
from {
|
||||||
|
transform: rotate(360deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
to {
|
||||||
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
import { createTheme } from '@acid-info/lsd-react'
|
||||||
|
|
||||||
|
export const light = createTheme({
|
||||||
|
breakpoints: {
|
||||||
|
xs: {},
|
||||||
|
sm: {},
|
||||||
|
lg: {},
|
||||||
|
xl: {},
|
||||||
|
},
|
||||||
|
typography: {},
|
||||||
|
palette: {
|
||||||
|
surface: {},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
export const dark = createTheme(
|
||||||
|
{
|
||||||
|
breakpoints: {},
|
||||||
|
typography: {},
|
||||||
|
palette: {
|
||||||
|
background: {
|
||||||
|
primary: 'black',
|
||||||
|
},
|
||||||
|
surface: {
|
||||||
|
primary: 'white',
|
||||||
|
},
|
||||||
|
text: {
|
||||||
|
primary: 'white',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
light,
|
||||||
|
)
|
|
@ -0,0 +1,24 @@
|
||||||
|
{
|
||||||
|
"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,
|
||||||
|
"baseUrl": ".",
|
||||||
|
"paths": {
|
||||||
|
"@/*": ["./src/*"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
|
||||||
|
"exclude": ["node_modules"]
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"$schema": "node_modules/lerna/schemas/lerna-schema.json",
|
||||||
|
"useNx": true,
|
||||||
|
"useWorkspaces": true,
|
||||||
|
"version": "0.0.0",
|
||||||
|
"packages": ["packages/*", "apps/*"]
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
{
|
||||||
|
"name": "@acid-info/logos-design-system",
|
||||||
|
"private": true,
|
||||||
|
"version": "0.0.0",
|
||||||
|
"scripts": {
|
||||||
|
"commit": "git-cz",
|
||||||
|
"test": "lerna run test",
|
||||||
|
"format:check": "prettier --config .prettierrc --check --ignore-unknown .",
|
||||||
|
"format:fix": "prettier --config .prettierrc --write --ignore-unknown -l .",
|
||||||
|
"prepare": "husky install"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@commitlint/cli": "^17.4.2",
|
||||||
|
"@commitlint/config-conventional": "^17.4.2",
|
||||||
|
"@types/node": "^18.11.18",
|
||||||
|
"commitizen": "^4.3.0",
|
||||||
|
"cz-conventional-changelog": "^3.3.0",
|
||||||
|
"husky": "^8.0.3",
|
||||||
|
"lerna": "^6.4.1",
|
||||||
|
"lint-staged": "^13.1.0",
|
||||||
|
"prettier": "^2.8.3"
|
||||||
|
},
|
||||||
|
"workspaces": [
|
||||||
|
"packages/*",
|
||||||
|
"apps/*"
|
||||||
|
],
|
||||||
|
"commitlint": {
|
||||||
|
"extends": [
|
||||||
|
"@commitlint/config-conventional"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"lint-staged": {
|
||||||
|
"*": "yarn run format:fix"
|
||||||
|
},
|
||||||
|
"config": {
|
||||||
|
"commitizen": {
|
||||||
|
"path": "node_modules/cz-conventional-changelog"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
# Logs
|
||||||
|
logs
|
||||||
|
*.log
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
pnpm-debug.log*
|
||||||
|
lerna-debug.log*
|
||||||
|
|
||||||
|
node_modules
|
||||||
|
dist
|
||||||
|
dist-ssr
|
||||||
|
*.local
|
||||||
|
|
||||||
|
# Editor directories and files
|
||||||
|
.vscode/*
|
||||||
|
!.vscode/extensions.json
|
||||||
|
.idea
|
||||||
|
.DS_Store
|
||||||
|
*.suo
|
||||||
|
*.ntvs*
|
||||||
|
*.njsproj
|
||||||
|
*.sln
|
||||||
|
*.sw?
|
|
@ -0,0 +1,46 @@
|
||||||
|
{
|
||||||
|
"name": "@acid-info/lsd-react",
|
||||||
|
"private": true,
|
||||||
|
"version": "0.0.0",
|
||||||
|
"type": "module",
|
||||||
|
"types": "./dist/index.d.ts",
|
||||||
|
"main": "./dist/lsd-react.js",
|
||||||
|
"require": "./dist/lsd-react.umd.cjs",
|
||||||
|
"scripts": {
|
||||||
|
"dev": "vite",
|
||||||
|
"build": "tsc && vite build",
|
||||||
|
"watch": "tsc && vite build --watch --emptyOutDir false",
|
||||||
|
"preview": "vite preview"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@emotion/react": "^11.10.5",
|
||||||
|
"@emotion/styled": "^11.10.5",
|
||||||
|
"clsx": "^1.2.1",
|
||||||
|
"lodash": "^4.17.21",
|
||||||
|
"react": "^18.2.0",
|
||||||
|
"react-dom": "^18.2.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@babel/plugin-transform-runtime": "^7.19.6",
|
||||||
|
"@babel/preset-env": "^7.20.2",
|
||||||
|
"@babel/preset-react": "^7.18.6",
|
||||||
|
"@babel/preset-typescript": "^7.18.6",
|
||||||
|
"@emotion/babel-plugin": "^11.10.5",
|
||||||
|
"@rollup/plugin-babel": "^6.0.3",
|
||||||
|
"@types/lodash": "^4.14.191",
|
||||||
|
"@types/react": "^18.0.26",
|
||||||
|
"@types/react-dom": "^18.0.9",
|
||||||
|
"@vitejs/plugin-react": "^3.0.0",
|
||||||
|
"sass": "^1.58.0",
|
||||||
|
"typescript": "^4.9.3",
|
||||||
|
"utility-types": "^3.10.0",
|
||||||
|
"vite": "^4.0.0",
|
||||||
|
"vite-plugin-dts": "^1.7.2"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@emotion/react": "^11.10.5",
|
||||||
|
"@emotion/styled": "^11.10.5",
|
||||||
|
"react": "^17.0.0 || ^18.0.0",
|
||||||
|
"react-dom": "^17.0.0 || ^18.0.0"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
import { LSD_NAMESPACE } from '../Theme/constants'
|
||||||
|
|
||||||
|
export const buttonClasses = {
|
||||||
|
root: `${LSD_NAMESPACE}-button`,
|
||||||
|
disabled: `${LSD_NAMESPACE}--disabled`,
|
||||||
|
large: `${LSD_NAMESPACE}--large`,
|
||||||
|
medium: `${LSD_NAMESPACE}--medium`,
|
||||||
|
small: `${LSD_NAMESPACE}--small`,
|
||||||
|
|
||||||
|
text: `${LSD_NAMESPACE}-button__text`,
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
import { css } from '@emotion/react'
|
||||||
|
import { withTheme } from '../Theme/withTheme'
|
||||||
|
import { buttonClasses } from './Button.classes'
|
||||||
|
|
||||||
|
export const ButtonStyles = withTheme(
|
||||||
|
(theme) => css`
|
||||||
|
.${buttonClasses.root} {
|
||||||
|
width: auto;
|
||||||
|
color: var(--lsd-text-primary);
|
||||||
|
background: none;
|
||||||
|
border: 1px solid var(--lsd-surface-primary);
|
||||||
|
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 6px 24px;
|
||||||
|
|
||||||
|
@media (max-width: ${theme.breakpoints.lg.width}px) {
|
||||||
|
color: red;
|
||||||
|
border-color: red;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.${buttonClasses.disabled} {
|
||||||
|
cursor: default;
|
||||||
|
color: var(--lsd-surface-disabled);
|
||||||
|
border-color: var(--lsd-surface-disabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
.${buttonClasses.large} {
|
||||||
|
padding: 10px 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.${buttonClasses.medium} {
|
||||||
|
}
|
||||||
|
|
||||||
|
.${buttonClasses.small} {
|
||||||
|
padding: 6px 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.${buttonClasses.root}:hover {
|
||||||
|
&:not(.${buttonClasses.disabled}) {
|
||||||
|
.${buttonClasses.text} {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
)
|
|
@ -0,0 +1,29 @@
|
||||||
|
import clsx from 'clsx'
|
||||||
|
import React from 'react'
|
||||||
|
import { buttonClasses } from './Button.classes'
|
||||||
|
|
||||||
|
export type ButtonProps = React.ButtonHTMLAttributes<HTMLButtonElement> & {
|
||||||
|
size?: 'large' | 'medium' | 'small'
|
||||||
|
}
|
||||||
|
|
||||||
|
export const Button: React.FC<ButtonProps> & {
|
||||||
|
classes: typeof buttonClasses
|
||||||
|
} = ({ size = 'medium', children, ...props }) => {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<button
|
||||||
|
{...props}
|
||||||
|
className={clsx(
|
||||||
|
props.className,
|
||||||
|
buttonClasses.root,
|
||||||
|
buttonClasses[size],
|
||||||
|
props.disabled && buttonClasses.disabled,
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<span className={buttonClasses.text}>{children}</span>
|
||||||
|
</button>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
Button.classes = buttonClasses
|
|
@ -0,0 +1 @@
|
||||||
|
export * from './Button'
|
|
@ -0,0 +1,19 @@
|
||||||
|
import { Global } from '@emotion/react'
|
||||||
|
import React, { useMemo } from 'react'
|
||||||
|
import { ButtonStyles } from '../Button/Button.styles'
|
||||||
|
import { Theme } from '../Theme'
|
||||||
|
import { defaultTheme } from '../Theme/defaultTheme'
|
||||||
|
|
||||||
|
export const CSSBaseline: React.FC<{ theme?: Theme }> = ({
|
||||||
|
theme = defaultTheme,
|
||||||
|
}) => {
|
||||||
|
const styles = useMemo(
|
||||||
|
() =>
|
||||||
|
[ButtonStyles]
|
||||||
|
.map((style) => (typeof style === 'function' ? style(theme) : style))
|
||||||
|
.map((style) => <Global key={style.name} styles={style} />),
|
||||||
|
[theme],
|
||||||
|
)
|
||||||
|
|
||||||
|
return <>{styles}</>
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
export * from './CSSBaseline'
|
|
@ -0,0 +1,25 @@
|
||||||
|
import { Global, ThemeProvider as EmotionThemeProvider } from '@emotion/react'
|
||||||
|
import React from 'react'
|
||||||
|
import { CSSBaseline } from '../CSSBaseline'
|
||||||
|
import { Theme } from './types'
|
||||||
|
|
||||||
|
export type ThemeProviderProps = React.PropsWithChildren<{
|
||||||
|
theme: Theme
|
||||||
|
}>
|
||||||
|
|
||||||
|
export const ThemeProvider: React.FC<ThemeProviderProps> = ({
|
||||||
|
theme,
|
||||||
|
children,
|
||||||
|
}) => {
|
||||||
|
return (
|
||||||
|
<ThemeContext.Provider value={{ theme }}>
|
||||||
|
<EmotionThemeProvider theme={theme}>{children}</EmotionThemeProvider>
|
||||||
|
<CSSBaseline theme={theme} />
|
||||||
|
<Global styles={theme.globalStyles} />
|
||||||
|
</ThemeContext.Provider>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ThemeContext = React.createContext({
|
||||||
|
theme: null as any,
|
||||||
|
})
|
|
@ -0,0 +1,35 @@
|
||||||
|
import {
|
||||||
|
Breakpoints,
|
||||||
|
TypographyProperties,
|
||||||
|
TypographyVariants,
|
||||||
|
VariantThemeProperties,
|
||||||
|
} from './types'
|
||||||
|
|
||||||
|
export const LSD_NAMESPACE = 'lsd'
|
||||||
|
|
||||||
|
export const THEME_BREAKPOINTS = ['xs', 'sm', 'md', 'lg', 'xl'] as Breakpoints[]
|
||||||
|
|
||||||
|
export const THEME_TYPOGRAPHY_VARIANTS = [
|
||||||
|
'headlineLg',
|
||||||
|
'headlineStd',
|
||||||
|
'headlineMd',
|
||||||
|
'headlineSm',
|
||||||
|
'titleLg',
|
||||||
|
'titleMd',
|
||||||
|
'titleSm',
|
||||||
|
'bodySm',
|
||||||
|
'bodyMd',
|
||||||
|
'bodyLg',
|
||||||
|
'labelLg',
|
||||||
|
'labelMd',
|
||||||
|
'labelSm',
|
||||||
|
] as TypographyVariants[]
|
||||||
|
|
||||||
|
export const THEME_TYPOGRAPHY_PROPERTIES = [
|
||||||
|
'fontSize',
|
||||||
|
'lineHeight',
|
||||||
|
] as TypographyProperties[]
|
||||||
|
|
||||||
|
export const THEME_VARIANT_PROPERTIES = [
|
||||||
|
'typography',
|
||||||
|
] as VariantThemeProperties[]
|
|
@ -0,0 +1,88 @@
|
||||||
|
import { css } from '@emotion/react'
|
||||||
|
import defaultsDeep from 'lodash/defaultsDeep'
|
||||||
|
import { pairs } from '../../utils/object.utils'
|
||||||
|
import { THEME_BREAKPOINTS, THEME_TYPOGRAPHY_VARIANTS } from './constants'
|
||||||
|
import { defaultTheme } from './defaultTheme'
|
||||||
|
import { createThemeGlobalStyles } from './globalStyles'
|
||||||
|
import type {
|
||||||
|
BreakpointStyles,
|
||||||
|
CreateThemeProps,
|
||||||
|
Theme,
|
||||||
|
ThemeBreakpoints,
|
||||||
|
TypographyVariants,
|
||||||
|
VariantThemeProperties,
|
||||||
|
} from './types'
|
||||||
|
|
||||||
|
const createTypographyStyles = (theme: CreateThemeProps, defaultTheme: Theme) =>
|
||||||
|
pairs<TypographyVariants>(THEME_TYPOGRAPHY_VARIANTS, (variant) => ({
|
||||||
|
...defaultTheme.typography[variant],
|
||||||
|
...(theme.typography[variant] ?? {}),
|
||||||
|
}))
|
||||||
|
|
||||||
|
const createBreakpointStyle = (
|
||||||
|
key: VariantThemeProperties,
|
||||||
|
all: BreakpointStyles[],
|
||||||
|
index: number,
|
||||||
|
theme: CreateThemeProps,
|
||||||
|
defaultTheme: Theme,
|
||||||
|
) => {
|
||||||
|
switch (key) {
|
||||||
|
case 'typography':
|
||||||
|
return pairs<TypographyVariants>(defaultTheme[key], (variant) => ({
|
||||||
|
...defaultTheme[key][variant],
|
||||||
|
...theme[key][variant],
|
||||||
|
...(all?.[index - 1]?.[key]?.[variant] ?? {}),
|
||||||
|
...(theme.breakpoints?.[THEME_BREAKPOINTS[index]]?.[key]?.[variant] ??
|
||||||
|
{}),
|
||||||
|
}))
|
||||||
|
|
||||||
|
default:
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const createBreakpointStyles = (
|
||||||
|
theme: CreateThemeProps,
|
||||||
|
defaultTheme: Theme,
|
||||||
|
): Theme['breakpoints'] =>
|
||||||
|
Object.fromEntries(
|
||||||
|
THEME_BREAKPOINTS.reduce<BreakpointStyles[]>(
|
||||||
|
(all, key, index) =>
|
||||||
|
[
|
||||||
|
...all,
|
||||||
|
{
|
||||||
|
...defaultTheme.breakpoints[key],
|
||||||
|
...theme.breakpoints[key],
|
||||||
|
...pairs(['typography'], (key) =>
|
||||||
|
createBreakpointStyle(
|
||||||
|
key as any,
|
||||||
|
all,
|
||||||
|
index,
|
||||||
|
theme,
|
||||||
|
defaultTheme,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
] as BreakpointStyles[],
|
||||||
|
[],
|
||||||
|
).map((styles, index) => [THEME_BREAKPOINTS[index], styles]),
|
||||||
|
) as ThemeBreakpoints
|
||||||
|
|
||||||
|
const createPaletteStyles = (theme: CreateThemeProps, defaultTheme: Theme) =>
|
||||||
|
defaultsDeep(theme.palette, defaultTheme.palette)
|
||||||
|
|
||||||
|
export const createTheme = (
|
||||||
|
props: CreateThemeProps,
|
||||||
|
from = defaultTheme,
|
||||||
|
): Theme => {
|
||||||
|
const theme: Theme = {
|
||||||
|
typography: createTypographyStyles(props, from),
|
||||||
|
breakpoints: createBreakpointStyles(props, from),
|
||||||
|
palette: createPaletteStyles(props, from),
|
||||||
|
globalStyles: css``,
|
||||||
|
}
|
||||||
|
|
||||||
|
theme.globalStyles = createThemeGlobalStyles(theme)
|
||||||
|
|
||||||
|
return theme
|
||||||
|
}
|
|
@ -0,0 +1,182 @@
|
||||||
|
import { css } from '@emotion/react'
|
||||||
|
import { createThemeGlobalStyles } from './globalStyles'
|
||||||
|
import { Theme } from './types'
|
||||||
|
|
||||||
|
export const defaultTheme: Theme = {
|
||||||
|
breakpoints: {
|
||||||
|
xs: {
|
||||||
|
width: 0,
|
||||||
|
typography: {
|
||||||
|
headlineLg: {},
|
||||||
|
headlineMd: {},
|
||||||
|
headlineStd: {},
|
||||||
|
headlineSm: {},
|
||||||
|
titleLg: {},
|
||||||
|
titleMd: {},
|
||||||
|
titleSm: {},
|
||||||
|
bodyLg: {},
|
||||||
|
bodyMd: {},
|
||||||
|
bodySm: {},
|
||||||
|
labelLg: {},
|
||||||
|
labelMd: {},
|
||||||
|
labelSm: {},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
sm: {
|
||||||
|
width: 400,
|
||||||
|
typography: {
|
||||||
|
headlineLg: {},
|
||||||
|
headlineMd: {},
|
||||||
|
headlineStd: {},
|
||||||
|
headlineSm: {},
|
||||||
|
titleLg: {},
|
||||||
|
titleMd: {},
|
||||||
|
titleSm: {},
|
||||||
|
bodyLg: {},
|
||||||
|
bodyMd: {},
|
||||||
|
bodySm: {},
|
||||||
|
labelLg: {},
|
||||||
|
labelMd: {},
|
||||||
|
labelSm: {},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
md: {
|
||||||
|
width: 768,
|
||||||
|
typography: {
|
||||||
|
headlineLg: {},
|
||||||
|
headlineMd: {},
|
||||||
|
headlineStd: {},
|
||||||
|
headlineSm: {},
|
||||||
|
titleLg: {},
|
||||||
|
titleMd: {},
|
||||||
|
titleSm: {},
|
||||||
|
bodyLg: {},
|
||||||
|
bodyMd: {},
|
||||||
|
bodySm: {},
|
||||||
|
labelLg: {},
|
||||||
|
labelMd: {},
|
||||||
|
labelSm: {},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
lg: {
|
||||||
|
width: 1024,
|
||||||
|
typography: {
|
||||||
|
headlineLg: {},
|
||||||
|
headlineMd: {},
|
||||||
|
headlineStd: {},
|
||||||
|
headlineSm: {},
|
||||||
|
titleLg: {},
|
||||||
|
titleMd: {},
|
||||||
|
titleSm: {},
|
||||||
|
bodyLg: {},
|
||||||
|
bodyMd: {},
|
||||||
|
bodySm: {},
|
||||||
|
labelLg: {},
|
||||||
|
labelMd: {},
|
||||||
|
labelSm: {},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
xl: {
|
||||||
|
width: 1200,
|
||||||
|
typography: {
|
||||||
|
headlineLg: {},
|
||||||
|
headlineMd: {},
|
||||||
|
headlineStd: {},
|
||||||
|
headlineSm: {},
|
||||||
|
titleLg: {},
|
||||||
|
titleMd: {},
|
||||||
|
titleSm: {},
|
||||||
|
bodyLg: {},
|
||||||
|
bodyMd: {},
|
||||||
|
bodySm: {},
|
||||||
|
labelLg: {},
|
||||||
|
labelMd: {},
|
||||||
|
labelSm: {},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
typography: {
|
||||||
|
headlineLg: {
|
||||||
|
fontSize: '2.875rem',
|
||||||
|
lineHeight: '3.25rem',
|
||||||
|
},
|
||||||
|
headlineMd: {
|
||||||
|
fontSize: '1.75rem',
|
||||||
|
lineHeight: '2.25rem',
|
||||||
|
},
|
||||||
|
headlineStd: {
|
||||||
|
fontSize: '2rem',
|
||||||
|
lineHeight: '2.5rem',
|
||||||
|
},
|
||||||
|
headlineSm: {
|
||||||
|
fontSize: '1.5rem',
|
||||||
|
lineHeight: '2rem',
|
||||||
|
},
|
||||||
|
titleLg: {
|
||||||
|
fontSize: '1.375rem',
|
||||||
|
lineHeight: '1.75rem',
|
||||||
|
},
|
||||||
|
titleMd: {
|
||||||
|
fontSize: '1rem',
|
||||||
|
lineHeight: '1.5rem',
|
||||||
|
},
|
||||||
|
titleSm: {
|
||||||
|
fontSize: '0.875rem',
|
||||||
|
lineHeight: '1.25rem',
|
||||||
|
},
|
||||||
|
bodyLg: {
|
||||||
|
fontSize: '1rem',
|
||||||
|
lineHeight: '1.5rem',
|
||||||
|
},
|
||||||
|
bodyMd: {
|
||||||
|
fontSize: '0.875rem',
|
||||||
|
lineHeight: '1.25rem',
|
||||||
|
},
|
||||||
|
bodySm: {
|
||||||
|
fontSize: '0.75rem',
|
||||||
|
lineHeight: '1rem',
|
||||||
|
},
|
||||||
|
labelLg: {
|
||||||
|
fontSize: '0.875rem',
|
||||||
|
lineHeight: '1.25rem',
|
||||||
|
},
|
||||||
|
labelMd: {
|
||||||
|
fontSize: '0.875rem',
|
||||||
|
lineHeight: '1.25rem',
|
||||||
|
},
|
||||||
|
labelSm: {
|
||||||
|
fontSize: '0.75rem',
|
||||||
|
lineHeight: '1rem',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
palette: {
|
||||||
|
background: {
|
||||||
|
primary: 'rgba(255, 255, 255, 1)',
|
||||||
|
secondary: 'rgba(0, 0, 0, 1)',
|
||||||
|
},
|
||||||
|
border: {
|
||||||
|
primary: 'rgba(51, 51, 56, 1)',
|
||||||
|
secondary: 'rgba(255, 255, 255, 1)',
|
||||||
|
tertiary: 'rgba(223, 223, 226, 1)',
|
||||||
|
},
|
||||||
|
surface: {
|
||||||
|
primary: 'rgba(0, 0, 0, 1)',
|
||||||
|
secondary: 'rgba(0, 0, 0, 0.34)',
|
||||||
|
tertiary: 'rgba(0, 0, 0, 0.2)',
|
||||||
|
disabled: 'rgba(168, 168, 168, 1)',
|
||||||
|
},
|
||||||
|
text: {
|
||||||
|
primary: 'rgba(0, 0, 0, 1)',
|
||||||
|
secondary: 'rgba(0, 0, 0, 0.34)',
|
||||||
|
placeholder: 'rgba(0, 0, 0, 0.34)',
|
||||||
|
disabled: 'rgba(0, 0, 0, 0.34)',
|
||||||
|
},
|
||||||
|
icons: {
|
||||||
|
primary: 'rgba(0, 0, 0, 1)',
|
||||||
|
disabled: 'rgba(0, 0, 0, 0.34)',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
globalStyles: css``,
|
||||||
|
}
|
||||||
|
|
||||||
|
defaultTheme.globalStyles = createThemeGlobalStyles(defaultTheme)
|
|
@ -0,0 +1,131 @@
|
||||||
|
import { css } from '@emotion/react'
|
||||||
|
import {
|
||||||
|
LSD_NAMESPACE,
|
||||||
|
THEME_BREAKPOINTS,
|
||||||
|
THEME_TYPOGRAPHY_PROPERTIES,
|
||||||
|
THEME_TYPOGRAPHY_VARIANTS,
|
||||||
|
} from './constants'
|
||||||
|
import { Breakpoints, Theme, TypographyVariants } from './types'
|
||||||
|
|
||||||
|
export const gs = {
|
||||||
|
breakpoint: (
|
||||||
|
theme: Theme,
|
||||||
|
breakpoint: Breakpoints,
|
||||||
|
content: string,
|
||||||
|
) => `@media (min-width: ${theme.breakpoints[breakpoint].width}px) {
|
||||||
|
${content}
|
||||||
|
}`,
|
||||||
|
|
||||||
|
vars: {
|
||||||
|
name: (...parts: string[]) => `--${[LSD_NAMESPACE, ...parts].join('-')}`,
|
||||||
|
wrap: (v: string, wrap = true) => (!wrap ? v : `var(${v})`),
|
||||||
|
define: (name: string, value: any) => `${name}: ${value};`,
|
||||||
|
typography: (
|
||||||
|
variant: TypographyVariants,
|
||||||
|
property: string,
|
||||||
|
breakpoint?: Breakpoints | 'default',
|
||||||
|
) => gs.vars.name(variant, property, ...(breakpoint ? [breakpoint] : [])),
|
||||||
|
palette: (category: string, variant: string) =>
|
||||||
|
gs.vars.name(category, variant),
|
||||||
|
},
|
||||||
|
|
||||||
|
all: (theme: Theme) =>
|
||||||
|
[gs.typography.all(theme), gs.palette.all(theme)].join('\n'),
|
||||||
|
|
||||||
|
typography: {
|
||||||
|
all: (theme: Theme) => [gs.typography.variants(theme)].join('\n'),
|
||||||
|
|
||||||
|
variants: (theme: Theme) =>
|
||||||
|
[
|
||||||
|
...THEME_TYPOGRAPHY_VARIANTS.flatMap((variant) =>
|
||||||
|
THEME_TYPOGRAPHY_PROPERTIES.map((prop) =>
|
||||||
|
gs.vars.define(
|
||||||
|
gs.vars.typography(variant, prop),
|
||||||
|
theme.typography[variant][prop],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
gs.typography.breakpoints(theme),
|
||||||
|
].join('\n'),
|
||||||
|
|
||||||
|
breakpoints: (theme: Theme) =>
|
||||||
|
THEME_BREAKPOINTS.map((breakpoint, index) =>
|
||||||
|
gs.breakpoint(
|
||||||
|
theme,
|
||||||
|
breakpoint,
|
||||||
|
gs.typography.breakpoint(theme, breakpoint, index),
|
||||||
|
),
|
||||||
|
).join('\n'),
|
||||||
|
|
||||||
|
breakpoint: (
|
||||||
|
theme: Theme,
|
||||||
|
breakpoint: Breakpoints,
|
||||||
|
breakpointIndex: number,
|
||||||
|
) =>
|
||||||
|
THEME_TYPOGRAPHY_VARIANTS.flatMap((variant) =>
|
||||||
|
THEME_TYPOGRAPHY_PROPERTIES.map((prop) => {
|
||||||
|
const value = theme.breakpoints[breakpoint].typography[variant][prop]
|
||||||
|
const current =
|
||||||
|
breakpointIndex > 0
|
||||||
|
? theme.breakpoints?.[THEME_BREAKPOINTS[breakpointIndex - 1]]
|
||||||
|
?.typography?.[variant]?.[prop]
|
||||||
|
: theme.typography[variant][prop]
|
||||||
|
|
||||||
|
return value !== current
|
||||||
|
? gs.vars.define(gs.vars.typography(variant, prop), value)
|
||||||
|
: undefined
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.filter((value) => !!value)
|
||||||
|
.join('\n'),
|
||||||
|
},
|
||||||
|
|
||||||
|
palette: {
|
||||||
|
all: (theme: Theme) => {
|
||||||
|
const palette = theme.palette as Record<string, Record<string, string>>
|
||||||
|
|
||||||
|
return [
|
||||||
|
...Object.keys(palette).flatMap((name) =>
|
||||||
|
Object.keys(palette[name]).map((variant) =>
|
||||||
|
gs.palette.color(name, variant, palette[name][variant]),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
`:root {
|
||||||
|
html, body {
|
||||||
|
background-color: ${theme.palette.background.primary};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
].join('\n')
|
||||||
|
},
|
||||||
|
|
||||||
|
color: (name: string, variant: string, value: string) =>
|
||||||
|
gs.vars.define(gs.vars.palette(name, variant), value),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
export const createThemeGlobalStyles = (() => {
|
||||||
|
return (theme: Theme) => {
|
||||||
|
const cache: any = {}
|
||||||
|
const key = theme as any as string
|
||||||
|
|
||||||
|
if (
|
||||||
|
cache[key] &&
|
||||||
|
process.env.NODE_ENV === 'production' &&
|
||||||
|
typeof window !== 'undefined'
|
||||||
|
)
|
||||||
|
return cache[key]
|
||||||
|
|
||||||
|
const styles = globalStyles.all(theme)
|
||||||
|
cache[key] = css`
|
||||||
|
:root {
|
||||||
|
${styles}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
return cache[key]
|
||||||
|
}
|
||||||
|
})()
|
||||||
|
|
||||||
|
export const globalStyles = gs
|
|
@ -0,0 +1,13 @@
|
||||||
|
export {
|
||||||
|
LSD_NAMESPACE,
|
||||||
|
THEME_BREAKPOINTS,
|
||||||
|
THEME_TYPOGRAPHY_PROPERTIES,
|
||||||
|
THEME_TYPOGRAPHY_VARIANTS,
|
||||||
|
THEME_VARIANT_PROPERTIES,
|
||||||
|
} from './constants'
|
||||||
|
export { createTheme } from './createTheme'
|
||||||
|
export { createThemeGlobalStyles, globalStyles } from './globalStyles'
|
||||||
|
export { ThemeProvider, type ThemeProviderProps } from './ThemeProvider'
|
||||||
|
export * from './types'
|
||||||
|
export { useTheme } from './useTheme'
|
||||||
|
export { withTheme } from './withTheme'
|
|
@ -0,0 +1,96 @@
|
||||||
|
import { SerializedStyles } from '@emotion/react'
|
||||||
|
import { CSSProperties } from 'react'
|
||||||
|
import { DeepPartial } from 'utility-types'
|
||||||
|
|
||||||
|
export type Breakpoints = 'xs' | 'sm' | 'md' | 'lg' | 'xl'
|
||||||
|
export type TypographyTypefaces = 'sans-serif' | 'serif' | 'mono'
|
||||||
|
export type TypographyVariants =
|
||||||
|
| 'headlineLg'
|
||||||
|
| 'headlineStd'
|
||||||
|
| 'headlineMd'
|
||||||
|
| 'headlineSm'
|
||||||
|
| 'titleLg'
|
||||||
|
| 'titleMd'
|
||||||
|
| 'titleSm'
|
||||||
|
| 'bodyLg'
|
||||||
|
| 'bodyMd'
|
||||||
|
| 'bodySm'
|
||||||
|
| 'labelLg'
|
||||||
|
| 'labelMd'
|
||||||
|
| 'labelSm'
|
||||||
|
|
||||||
|
export type VariantThemeProperties = keyof Pick<Theme, 'typography'>
|
||||||
|
|
||||||
|
export type TypographyStyles = Pick<CSSProperties, 'fontSize' | 'lineHeight'>
|
||||||
|
export type TypographyProperties = keyof TypographyStyles
|
||||||
|
export type ThemeTypography<T extends string = TypographyVariants> = {
|
||||||
|
[key in T]: TypographyStyles
|
||||||
|
}
|
||||||
|
|
||||||
|
export type ThemePalette = {
|
||||||
|
background: {
|
||||||
|
primary: string
|
||||||
|
secondary: string
|
||||||
|
}
|
||||||
|
border: {
|
||||||
|
primary: string
|
||||||
|
secondary: string
|
||||||
|
tertiary: string
|
||||||
|
}
|
||||||
|
surface: {
|
||||||
|
primary: string
|
||||||
|
secondary: string
|
||||||
|
tertiary: string
|
||||||
|
disabled: string
|
||||||
|
}
|
||||||
|
text: {
|
||||||
|
primary: string
|
||||||
|
secondary: string
|
||||||
|
placeholder: string
|
||||||
|
disabled: string
|
||||||
|
}
|
||||||
|
icons: {
|
||||||
|
primary: string
|
||||||
|
disabled: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export type BreakpointStyles = {
|
||||||
|
width: number
|
||||||
|
} & Pick<Theme, 'typography'>
|
||||||
|
|
||||||
|
export type ThemeBreakpoints = {
|
||||||
|
[key in Breakpoints]: BreakpointStyles
|
||||||
|
}
|
||||||
|
|
||||||
|
export type Theme = {
|
||||||
|
breakpoints: ThemeBreakpoints
|
||||||
|
typography: ThemeTypography
|
||||||
|
palette: ThemePalette
|
||||||
|
globalStyles: SerializedStyles
|
||||||
|
}
|
||||||
|
|
||||||
|
export type ThemeOptionBreakpointStyles = Partial<
|
||||||
|
Omit<BreakpointStyles, 'width' | 'typography'> & {
|
||||||
|
width?: number
|
||||||
|
typography: ThemeOptionTypography
|
||||||
|
}
|
||||||
|
>
|
||||||
|
|
||||||
|
export type ThemeOptionBreakpoints = {
|
||||||
|
[K in keyof ThemeBreakpoints]?: ThemeOptionBreakpointStyles
|
||||||
|
}
|
||||||
|
|
||||||
|
export type ThemeOptionTypographyStyle = TypographyStyles
|
||||||
|
export type ThemeOptionTypography = DeepPartial<ThemeTypography>
|
||||||
|
export type ThemeOptionPalette = DeepPartial<ThemePalette>
|
||||||
|
|
||||||
|
export type CreateThemeProps = {
|
||||||
|
breakpoints: ThemeOptionBreakpoints
|
||||||
|
typography: ThemeOptionTypography
|
||||||
|
palette: ThemeOptionPalette
|
||||||
|
}
|
||||||
|
|
||||||
|
export type ThemeContext = {
|
||||||
|
theme: Theme
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
import { useContext } from 'react'
|
||||||
|
import { defaultTheme } from './defaultTheme'
|
||||||
|
import { ThemeContext } from './ThemeProvider'
|
||||||
|
import type { Theme } from './types'
|
||||||
|
|
||||||
|
export const useTheme = <T extends Theme>() => {
|
||||||
|
const theme = useContext(ThemeContext).theme as T
|
||||||
|
|
||||||
|
return theme ?? defaultTheme
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
import { SerializedStyles } from '@emotion/react'
|
||||||
|
import { Theme } from './types'
|
||||||
|
|
||||||
|
export const withTheme =
|
||||||
|
(style: (theme: Theme) => SerializedStyles) => (theme: Theme) =>
|
||||||
|
style(theme)
|
|
@ -0,0 +1,2 @@
|
||||||
|
export * from './components/Button'
|
||||||
|
export * from './components/Theme'
|
|
@ -0,0 +1,10 @@
|
||||||
|
export const pairs = <K extends string = string, T = any>(
|
||||||
|
obj: string[] | Object,
|
||||||
|
map: (key: K, index: number) => T,
|
||||||
|
): Record<K, T> =>
|
||||||
|
Object.fromEntries(
|
||||||
|
(Array.isArray(obj) ? obj : Object.keys(obj)).map((key, index) => [
|
||||||
|
key,
|
||||||
|
map(key, index),
|
||||||
|
]),
|
||||||
|
)
|
|
@ -0,0 +1 @@
|
||||||
|
/// <reference types="vite/client" />
|
|
@ -0,0 +1,22 @@
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "ESNext",
|
||||||
|
"useDefineForClassFields": true,
|
||||||
|
"lib": ["DOM", "DOM.Iterable", "ESNext"],
|
||||||
|
"allowJs": false,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"esModuleInterop": false,
|
||||||
|
"allowSyntheticDefaultImports": true,
|
||||||
|
"strict": true,
|
||||||
|
"forceConsistentCasingInFileNames": true,
|
||||||
|
"module": "ESNext",
|
||||||
|
"moduleResolution": "Node",
|
||||||
|
"resolveJsonModule": true,
|
||||||
|
"isolatedModules": true,
|
||||||
|
"noEmit": true,
|
||||||
|
"jsx": "react-jsx",
|
||||||
|
"declaration": true
|
||||||
|
},
|
||||||
|
"include": ["src"],
|
||||||
|
"references": [{ "path": "./tsconfig.node.json" }]
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"composite": true,
|
||||||
|
"module": "ESNext",
|
||||||
|
"moduleResolution": "Node",
|
||||||
|
"allowSyntheticDefaultImports": true,
|
||||||
|
"resolveJsonModule": true
|
||||||
|
},
|
||||||
|
"include": ["vite.config.ts"]
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
import react from '@vitejs/plugin-react'
|
||||||
|
import path from 'path'
|
||||||
|
import { defineConfig } from 'vite'
|
||||||
|
import dts from 'vite-plugin-dts'
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
plugins: [
|
||||||
|
react({
|
||||||
|
jsxImportSource: '@emotion/react',
|
||||||
|
babel: {
|
||||||
|
plugins: ['@emotion/babel-plugin'],
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
dts({
|
||||||
|
include: ['src'],
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
|
||||||
|
build: {
|
||||||
|
minify: false,
|
||||||
|
outDir: 'dist',
|
||||||
|
|
||||||
|
lib: {
|
||||||
|
entry: path.resolve(__dirname, './src/index.ts'),
|
||||||
|
name: 'lsd-react',
|
||||||
|
fileName: 'lsd-react',
|
||||||
|
},
|
||||||
|
rollupOptions: {
|
||||||
|
external: ['react', 'react-dom', '@emotion/styled', '@emotion/react'],
|
||||||
|
output: {
|
||||||
|
globals: {
|
||||||
|
react: 'React',
|
||||||
|
'react-dom': 'ReactDOM',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
|
@ -0,0 +1,20 @@
|
||||||
|
{
|
||||||
|
"$schema": "https://json.schemastore.org/tsconfig",
|
||||||
|
"display": "Default",
|
||||||
|
"compilerOptions": {
|
||||||
|
"composite": false,
|
||||||
|
"declaration": true,
|
||||||
|
"declarationMap": true,
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"forceConsistentCasingInFileNames": true,
|
||||||
|
"inlineSources": false,
|
||||||
|
"isolatedModules": true,
|
||||||
|
"moduleResolution": "node",
|
||||||
|
"noUnusedLocals": false,
|
||||||
|
"noUnusedParameters": false,
|
||||||
|
"preserveWatchOutput": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"strict": true
|
||||||
|
},
|
||||||
|
"exclude": ["node_modules"]
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
{
|
||||||
|
"$schema": "https://json.schemastore.org/tsconfig",
|
||||||
|
"display": "React Library",
|
||||||
|
"extends": "./base.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"jsx": "react-jsx",
|
||||||
|
"lib": ["ES2015"],
|
||||||
|
"module": "ESNext",
|
||||||
|
"target": "es6"
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue