AAAA
This commit is contained in:
commit
a756a40572
27 changed files with 1152 additions and 0 deletions
18
.eslintrc.cjs
Normal file
18
.eslintrc.cjs
Normal file
|
@ -0,0 +1,18 @@
|
|||
module.exports = {
|
||||
root: true,
|
||||
env: { browser: true, es2020: true },
|
||||
extends: [
|
||||
'eslint:recommended',
|
||||
'plugin:@typescript-eslint/recommended',
|
||||
'plugin:react-hooks/recommended',
|
||||
],
|
||||
ignorePatterns: ['dist', '.eslintrc.cjs'],
|
||||
parser: '@typescript-eslint/parser',
|
||||
plugins: ['react-refresh'],
|
||||
rules: {
|
||||
'react-refresh/only-export-components': [
|
||||
'warn',
|
||||
{ allowConstantExport: true },
|
||||
],
|
||||
},
|
||||
}
|
24
.gitignore
vendored
Normal file
24
.gitignore
vendored
Normal file
|
@ -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?
|
2
.prettierrc.yml
Normal file
2
.prettierrc.yml
Normal file
|
@ -0,0 +1,2 @@
|
|||
semi: false
|
||||
singleQuote: true
|
30
README.md
Normal file
30
README.md
Normal file
|
@ -0,0 +1,30 @@
|
|||
# React + TypeScript + Vite
|
||||
|
||||
This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
|
||||
|
||||
Currently, two official plugins are available:
|
||||
|
||||
- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh
|
||||
- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
|
||||
|
||||
## Expanding the ESLint configuration
|
||||
|
||||
If you are developing a production application, we recommend updating the configuration to enable type aware lint rules:
|
||||
|
||||
- Configure the top-level `parserOptions` property like this:
|
||||
|
||||
```js
|
||||
export default {
|
||||
// other rules...
|
||||
parserOptions: {
|
||||
ecmaVersion: 'latest',
|
||||
sourceType: 'module',
|
||||
project: ['./tsconfig.json', './tsconfig.node.json'],
|
||||
tsconfigRootDir: __dirname,
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
- Replace `plugin:@typescript-eslint/recommended` to `plugin:@typescript-eslint/recommended-type-checked` or `plugin:@typescript-eslint/strict-type-checked`
|
||||
- Optionally add `plugin:@typescript-eslint/stylistic-type-checked`
|
||||
- Install [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) and add `plugin:react/recommended` & `plugin:react/jsx-runtime` to the `extends` list
|
BIN
bun.lockb
Normal file
BIN
bun.lockb
Normal file
Binary file not shown.
17
components.json
Normal file
17
components.json
Normal file
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"$schema": "https://ui.shadcn.com/schema.json",
|
||||
"style": "default",
|
||||
"rsc": false,
|
||||
"tsx": true,
|
||||
"tailwind": {
|
||||
"config": "tailwind.config.ts",
|
||||
"css": "src/index.css",
|
||||
"baseColor": "slate",
|
||||
"cssVariables": true,
|
||||
"prefix": ""
|
||||
},
|
||||
"aliases": {
|
||||
"components": "@/components",
|
||||
"utils": "@/lib/utils"
|
||||
}
|
||||
}
|
13
index.html
Normal file
13
index.html
Normal file
|
@ -0,0 +1,13 @@
|
|||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>1000 руб за мои страдания</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<script type="module" src="/src/main.tsx"></script>
|
||||
</body>
|
||||
</html>
|
40
package.json
Normal file
40
package.json
Normal file
|
@ -0,0 +1,40 @@
|
|||
{
|
||||
"name": "darts",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "bunx --bun vite",
|
||||
"build": "tsc -b && bunx --bun vite build",
|
||||
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
|
||||
"preview": "bunx --bun vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"@radix-ui/react-label": "^2.1.0",
|
||||
"@radix-ui/react-slot": "^1.1.0",
|
||||
"class-variance-authority": "^0.7.0",
|
||||
"clsx": "^2.1.1",
|
||||
"immer": "^10.1.1",
|
||||
"lucide-react": "^0.396.0",
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1",
|
||||
"tailwind-merge": "^2.3.0",
|
||||
"tailwindcss-animate": "^1.0.7",
|
||||
"zustand": "^4.5.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react": "^18.3.3",
|
||||
"@types/react-dom": "^18.3.0",
|
||||
"@typescript-eslint/eslint-plugin": "^7.13.1",
|
||||
"@typescript-eslint/parser": "^7.13.1",
|
||||
"@vitejs/plugin-react-swc": "^3.5.0",
|
||||
"autoprefixer": "^10.4.19",
|
||||
"eslint": "^8.57.0",
|
||||
"eslint-plugin-react-hooks": "^4.6.2",
|
||||
"eslint-plugin-react-refresh": "^0.4.7",
|
||||
"postcss": "^8.4.38",
|
||||
"tailwindcss": "^3.4.4",
|
||||
"typescript": "^5.2.2",
|
||||
"vite": "^5.3.1"
|
||||
}
|
||||
}
|
6
postcss.config.js
Normal file
6
postcss.config.js
Normal file
|
@ -0,0 +1,6 @@
|
|||
export default {
|
||||
plugins: {
|
||||
tailwindcss: {},
|
||||
autoprefixer: {},
|
||||
},
|
||||
}
|
1
public/vite.svg
Normal file
1
public/vite.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>
|
After Width: | Height: | Size: 1.5 KiB |
3
src/App.css
Normal file
3
src/App.css
Normal file
|
@ -0,0 +1,3 @@
|
|||
html, body, #root {
|
||||
@apply h-full w-full;
|
||||
}
|
87
src/App.tsx
Normal file
87
src/App.tsx
Normal file
|
@ -0,0 +1,87 @@
|
|||
import { create } from 'zustand'
|
||||
import './App.css'
|
||||
import { produce } from 'immer'
|
||||
import doska from './assets/doska.svg'
|
||||
import { useState } from 'react'
|
||||
import { Button } from './components/ui/button'
|
||||
import { Input } from './components/ui/input'
|
||||
import { Label } from './components/ui/label'
|
||||
|
||||
interface Player {
|
||||
points: number
|
||||
throws: number
|
||||
}
|
||||
|
||||
interface Game {
|
||||
players: Player[]
|
||||
currentPlayerIdx: number
|
||||
round: number
|
||||
|
||||
started: boolean
|
||||
startedAt: number
|
||||
|
||||
start(nplayers: number): void
|
||||
}
|
||||
|
||||
const useGame = create<Game>((set) => ({
|
||||
players: [],
|
||||
currentPlayerIdx: -1,
|
||||
round: 0,
|
||||
started: false,
|
||||
startedAt: -1,
|
||||
start(nplayers) {
|
||||
set(state => produce(state, state => {
|
||||
state.players = Array.from({ length: nplayers }, () => ({
|
||||
points: 0,
|
||||
throws: 0
|
||||
}))
|
||||
state.currentPlayerIdx = 0
|
||||
}))
|
||||
}
|
||||
}))
|
||||
|
||||
export default function App() {
|
||||
const [startedAt, started, round] = useGame(game => [game.startedAt, game.started, game.round])
|
||||
|
||||
return (
|
||||
<div className='flex flex-col h-full w-full'>
|
||||
{/* Верхняя часть: доска */}
|
||||
<div className='flex flex-col h-full justify-start items-center'>
|
||||
<div className="flex flex-row justify-between items-center w-full">
|
||||
<div className="flex flex-row justify-start">
|
||||
<Label htmlFor="round">Раунд</Label>
|
||||
<p id="round">{started ? `#${round}` : "Игра не начата"}</p></div>
|
||||
<p>{started ? new Date(Date.now() - startedAt).toLocaleTimeString() : ""}</p>
|
||||
</div>
|
||||
|
||||
<Board />
|
||||
</div>
|
||||
{/* Нижняя часть: управление игрой */}
|
||||
<Control />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function Board() {
|
||||
const [points, setPoints] = useState(0)
|
||||
|
||||
return (
|
||||
<img src={doska} onMouseMove={e => {}} />
|
||||
)
|
||||
}
|
||||
|
||||
function Control() {
|
||||
const [started, round, start, players] = useGame(game => [game.started, game.round, game.start, game.players])
|
||||
const [nplayers, setNplayers] = useState(2)
|
||||
|
||||
return (
|
||||
<div className='flex flex-col h-full justify-start gap-2'>
|
||||
<Label htmlFor="nplayers">Количество игроков</Label>
|
||||
<Input id="nplayers" onChange={ev => setNplayers(parseInt(ev.target.value))} type="number" value={nplayers} disabled={started} />
|
||||
|
||||
<Button onClick={() => start(nplayers)} disabled={started}>
|
||||
{"Начать игру"}
|
||||
</Button>
|
||||
</div>
|
||||
)
|
||||
}
|
444
src/assets/doska.svg
Normal file
444
src/assets/doska.svg
Normal file
|
@ -0,0 +1,444 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
version="1.0"
|
||||
width="453"
|
||||
height="453"
|
||||
id="svg5532"
|
||||
sodipodi:docname="dartboard.svg"
|
||||
inkscape:version="1.1.1 (3bf5ae0d25, 2021-09-20)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview1060"
|
||||
pagecolor="#505050"
|
||||
bordercolor="#ffffff"
|
||||
borderopacity="1"
|
||||
inkscape:pageshadow="0"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pagecheckerboard="1"
|
||||
showgrid="false"
|
||||
inkscape:zoom="1.8122538"
|
||||
inkscape:cx="350.39242"
|
||||
inkscape:cy="147.60626"
|
||||
inkscape:window-width="3440"
|
||||
inkscape:window-height="1376"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="27"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg5532" />
|
||||
<defs
|
||||
id="defs5534">
|
||||
<marker
|
||||
refX="0"
|
||||
refY="0"
|
||||
orient="auto"
|
||||
id="Arrow2Send"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.97309,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z"
|
||||
transform="matrix(-0.3,0,0,-0.3,1.5,0)"
|
||||
id="path9898"
|
||||
style="font-size:12px;fill:#62adff;fill-opacity:1;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" />
|
||||
</marker>
|
||||
</defs>
|
||||
<g
|
||||
transform="translate(-9.31263,-200.1479)"
|
||||
id="layer1">
|
||||
<g
|
||||
transform="translate(235.81263,426.6479)"
|
||||
id="Board">
|
||||
<g
|
||||
id="BaseBoard">
|
||||
<path
|
||||
d="M 226.5,0 A 226.5,226.5 0 1 1 -226.5,2.7737334e-14 A 226.5,226.5 0 1 1 226.5,-5.5474668e-14 z"
|
||||
id="path1307"
|
||||
style="opacity:1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.10000002;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
|
||||
</g>
|
||||
<g
|
||||
id="Inside Spider"
|
||||
style="stroke:#d0edfd;stroke-width:1.10000002;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1">
|
||||
<path
|
||||
d="M 170.55,0 A 170.55,170.55 0 1 1 -170.55,2.0885662e-14 A 170.55,170.55 0 1 1 170.55,-4.1771323e-14 z"
|
||||
id="DoubleRed"
|
||||
style="opacity:1;fill:#ff0000;fill-opacity:1;fill-rule:evenodd" />
|
||||
<path
|
||||
d="M 146.91298,0 A 146.91298,146.91298 0 1 1 -146.91298,0 146.91298,146.91298 0 1 1 146.91298,0 Z"
|
||||
id="path2195"
|
||||
style="opacity:1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke-width:1.00096" />
|
||||
<path
|
||||
d="M 107.55,0 A 107.55,107.55 0 1 1 -107.55,1.3170642e-14 A 107.55,107.55 0 1 1 107.55,-2.6341283e-14 z"
|
||||
id="TrebleRed"
|
||||
style="opacity:1;fill:#ff0000;fill-opacity:1;fill-rule:evenodd" />
|
||||
<path
|
||||
d="M 85.734511,0 A 85.734511,85.734511 0 1 1 -85.734511,0 85.734511,85.734511 0 1 1 85.734511,0 Z"
|
||||
id="path2197"
|
||||
style="opacity:1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke-width:0.957928" />
|
||||
<g
|
||||
id="GreenDoubleSpiders"
|
||||
style="opacity:1;fill:#00a000;fill-opacity:1;fill-rule:evenodd">
|
||||
<path
|
||||
d="M 170.55,0 A 170.55,170.55 0 0 1 162.20269,52.70285 L 0,0 z"
|
||||
transform="matrix(-0.45399,-0.891007,0.891007,-0.45399,0,0)"
|
||||
id="path4826"
|
||||
style="fill:#00a000;fill-opacity:1" />
|
||||
<path
|
||||
d="M 170.55,0 A 170.55,170.55 0 0 1 162.20269,52.70285 L 0,0 z"
|
||||
transform="matrix(-0.891006,-0.453991,0.453991,-0.891006,0,0)"
|
||||
id="path4830"
|
||||
style="fill:#00a000;fill-opacity:1" />
|
||||
<path
|
||||
d="M 170.55,0 A 170.55,170.55 0 0 1 162.20269,52.70285 L 0,0 z"
|
||||
transform="matrix(-0.987688,0.156434,-0.156434,-0.987688,0,0)"
|
||||
id="path4832"
|
||||
style="fill:#00a000;fill-opacity:1" />
|
||||
<path
|
||||
d="M 170.55,0 A 170.55,170.55 0 0 1 162.20269,52.70285 L 0,0 z"
|
||||
transform="matrix(-0.707107,0.707106,-0.707106,-0.707107,0,0)"
|
||||
id="path4834"
|
||||
style="fill:#00a000;fill-opacity:1" />
|
||||
<path
|
||||
d="M 170.55,0 A 170.55,170.55 0 0 1 162.20269,52.70285 L 0,0 z"
|
||||
transform="matrix(-0.156435,0.987688,-0.987688,-0.156435,0,0)"
|
||||
id="path4836"
|
||||
style="fill:#00a000;fill-opacity:1" />
|
||||
<path
|
||||
d="M 170.55,0 A 170.55,170.55 0 0 1 162.20269,52.70285 L 0,0 z"
|
||||
transform="matrix(0.45399,0.891007,-0.891007,0.45399,0,0)"
|
||||
id="path4838"
|
||||
style="fill:#00a000;fill-opacity:1" />
|
||||
<path
|
||||
d="M 170.55,0 A 170.55,170.55 0 0 1 162.20269,52.70285 L 0,0 z"
|
||||
transform="matrix(0.891006,0.453991,-0.453991,0.891006,0,0)"
|
||||
id="path4840"
|
||||
style="fill:#00a000;fill-opacity:1" />
|
||||
<path
|
||||
d="M 170.55,0 A 170.55,170.55 0 0 1 162.20269,52.70285 L 0,0 z"
|
||||
transform="matrix(0.987688,-0.156434,0.156434,0.987688,0,0)"
|
||||
id="path4842"
|
||||
style="fill:#00a000;fill-opacity:1" />
|
||||
<path
|
||||
d="M 170.55,0 A 170.55,170.55 0 0 1 162.20269,52.70285 L 0,0 z"
|
||||
transform="matrix(0.707107,-0.707106,0.707106,0.707107,0,0)"
|
||||
id="path4844"
|
||||
style="fill:#00a000;fill-opacity:1" />
|
||||
<path
|
||||
d="M 170.55,0 A 170.55,170.55 0 0 1 162.20269,52.70285 L 0,0 z"
|
||||
transform="matrix(0.156435,-0.987688,0.987688,0.156435,0,0)"
|
||||
id="path4846"
|
||||
style="fill:#00a000;fill-opacity:1" />
|
||||
</g>
|
||||
<g
|
||||
id="g4876"
|
||||
style="opacity:1;fill:#e7e4c7;fill-opacity:1;fill-rule:evenodd">
|
||||
<path
|
||||
d="m -66.614831,-130.81306 a 146.84024,146.84024 0 0 1 43.693212,-14.19675 L 0.04915736,0.02259513 Z"
|
||||
id="path4878"
|
||||
style="stroke-width:1.00046" />
|
||||
<path
|
||||
d="m -130.83239,-66.636197 a 146.87608,146.87608 0 0 1 27.0105,-37.176703 L 0.03510631,0.04423649 Z"
|
||||
id="path4880"
|
||||
style="stroke-width:1.0007" />
|
||||
<path
|
||||
d="m -145.08371,22.980164 a 146.90004,146.90004 3.5625082 0 1 2e-5,-45.960459 L 0.00775386,-5.8949186e-6 Z"
|
||||
id="path4882"
|
||||
style="stroke-width:1.00087" />
|
||||
<path
|
||||
d="M -103.71911,103.70974 A 146.731,146.731 84.345034 0 1 -130.70287,66.569709 L 0.03545567,-0.04467679 Z"
|
||||
id="path4884"
|
||||
style="stroke-width:0.999716" />
|
||||
<path
|
||||
d="M -22.935899,145.09705 A 146.92846,146.92846 3.5625082 0 1 -66.65534,130.89171 L 0.04886028,-0.02245864 Z"
|
||||
id="path4886"
|
||||
style="stroke-width:1.00106" />
|
||||
<path
|
||||
d="m 66.541322,130.66961 a 146.67951,146.67951 84.345034 0 1 -43.645387,14.1812 L -0.04969816,-0.02284371 Z"
|
||||
id="path4888"
|
||||
style="stroke-width:0.999365" />
|
||||
<path
|
||||
d="M 130.75061,66.594361 A 146.78454,146.78454 0 0 1 103.75694,103.7479 L -0.03532682,-0.04451434 Z"
|
||||
id="path4890"
|
||||
style="stroke-width:1.00008" />
|
||||
<path
|
||||
d="m 145.10415,-22.982174 a 146.91288,146.91288 0 0 1 -2e-5,45.964478 L 0,5.8734336e-6 Z"
|
||||
id="path4892"
|
||||
style="stroke-width:1.00095" />
|
||||
<path
|
||||
d="m 103.76307,-103.75374 a 146.79296,146.79296 0 0 1 26.99515,37.155715 L -0.03530643,0.04448874 Z"
|
||||
id="path4894"
|
||||
style="stroke-width:1.00014" />
|
||||
<path
|
||||
d="m 22.897236,-144.85771 a 146.68651,146.68651 0 0 1 43.647449,14.18195 L -0.04967436,0.02283283 Z"
|
||||
id="path4896"
|
||||
style="stroke-width:0.999413" />
|
||||
</g>
|
||||
<g
|
||||
id="GreenTrebleSpiders"
|
||||
style="opacity:1;fill:#00a000;fill-opacity:1;fill-rule:evenodd">
|
||||
<path
|
||||
d="M 107.55,0 A 107.55,107.55 0 0 1 102.28613,33.234779 L 0,0 z"
|
||||
transform="matrix(-0.45399,-0.891007,0.891007,-0.45399,0,0)"
|
||||
id="path4856" />
|
||||
<path
|
||||
d="M 107.55,0 A 107.55,107.55 0 0 1 102.28613,33.234779 L 0,0 z"
|
||||
transform="matrix(-0.891006,-0.453991,0.453991,-0.891006,0,0)"
|
||||
id="path4858" />
|
||||
<path
|
||||
d="M 107.55,0 A 107.55,107.55 0 0 1 102.28613,33.234779 L 0,0 z"
|
||||
transform="matrix(-0.987688,0.156434,-0.156434,-0.987688,0,0)"
|
||||
id="path4860" />
|
||||
<path
|
||||
d="M 107.55,0 A 107.55,107.55 0 0 1 102.28613,33.234779 L 0,0 z"
|
||||
transform="matrix(-0.707107,0.707106,-0.707106,-0.707107,0,0)"
|
||||
id="path4862" />
|
||||
<path
|
||||
d="M 107.55,0 A 107.55,107.55 0 0 1 102.28613,33.234779 L 0,0 z"
|
||||
transform="matrix(-0.156435,0.987688,-0.987688,-0.156435,0,0)"
|
||||
id="path4864" />
|
||||
<path
|
||||
d="M 107.55,0 A 107.55,107.55 0 0 1 102.28613,33.234779 L 0,0 z"
|
||||
transform="matrix(0.45399,0.891007,-0.891007,0.45399,0,0)"
|
||||
id="path4866" />
|
||||
<path
|
||||
d="M 107.55,0 A 107.55,107.55 0 0 1 102.28613,33.234779 L 0,0 z"
|
||||
transform="matrix(0.891006,0.453991,-0.453991,0.891006,0,0)"
|
||||
id="path4868" />
|
||||
<path
|
||||
d="M 107.55,0 A 107.55,107.55 0 0 1 102.28613,33.234779 L 0,0 z"
|
||||
transform="matrix(0.987688,-0.156434,0.156434,0.987688,0,0)"
|
||||
id="path4870" />
|
||||
<path
|
||||
d="M 107.55,0 A 107.55,107.55 0 0 1 102.28613,33.234779 L 0,0 z"
|
||||
id="path4872"
|
||||
transform="matrix(0.707107,-0.707106,0.707106,0.707107,0,0)" />
|
||||
<path
|
||||
d="M 107.55,0 A 107.55,107.55 0 0 1 102.28613,33.234779 L 0,0 z"
|
||||
transform="matrix(0.156435,-0.987688,0.987688,0.156435,0,0)"
|
||||
id="path4874" />
|
||||
</g>
|
||||
<g
|
||||
id="g5771"
|
||||
style="opacity:1;fill:#e7e4c7;fill-opacity:1;fill-rule:evenodd">
|
||||
<path
|
||||
d="m -38.833913,-76.321755 a 85.694189,85.694189 0 0 1 25.498829,-8.285053 L 0.07038427,0.03235206 Z"
|
||||
id="path5773"
|
||||
style="fill:#e7e4c7;fill-opacity:1;stroke-width:0.957477" />
|
||||
<path
|
||||
d="m -76.229063,-38.802647 a 85.610831,85.610831 82.981878 0 1 15.743825,-21.669485 L 0.05071872,0.06390925 Z"
|
||||
id="path5775"
|
||||
style="fill:#e7e4c7;fill-opacity:1;stroke-width:0.956546" />
|
||||
<path
|
||||
d="m -84.815746,13.435193 a 85.884098,85.884098 88.977296 0 1 1.1e-5,-26.870466 L 0.01098178,-5.1174552e-6 Z"
|
||||
id="path5777"
|
||||
style="fill:#e7e4c7;fill-opacity:1;stroke-width:0.959599" />
|
||||
<path
|
||||
d="M -60.542317,60.529123 A 85.690985,85.690985 0 0 1 -76.300853,38.839328 L 0.05040196,-0.06351024 Z"
|
||||
id="path5779"
|
||||
style="fill:#e7e4c7;fill-opacity:1;stroke-width:0.957441" />
|
||||
<path
|
||||
d="M -13.335505,84.608722 A 85.696138,85.696138 1.7881672 0 1 -38.834904,76.323448 L 0.07037326,-0.03234708 Z"
|
||||
id="path5781"
|
||||
style="fill:#e7e4c7;fill-opacity:1;stroke-width:0.957499" />
|
||||
<path
|
||||
d="M 38.823169,76.300864 A 85.670808,85.670808 0 0 1 13.331297,84.583656 L -0.07051328,-0.03241135 Z"
|
||||
id="path5783"
|
||||
style="fill:#e7e4c7;fill-opacity:1;stroke-width:0.957216" />
|
||||
<path
|
||||
d="M 76.275705,38.826567 A 85.662947,85.662947 28.154966 0 1 60.522296,60.509243 L -0.05051285,-0.06364984 Z"
|
||||
id="path5785"
|
||||
style="fill:#e7e4c7;fill-opacity:1;stroke-width:0.957128" />
|
||||
<path
|
||||
d="m 84.274967,-13.349618 a 85.337062,85.337062 0 0 1 -1.1e-5,26.699316 L -0.01145986,5.3402359e-6 Z"
|
||||
id="path5787"
|
||||
style="fill:#e7e4c7;fill-opacity:1;stroke-width:0.953487" />
|
||||
<path
|
||||
d="m 60.4633,-60.449992 a 85.579859,85.579859 22.5 0 1 15.738099,21.661667 L -0.05084094,0.06406339 Z"
|
||||
id="path5789"
|
||||
style="fill:#e7e4c7;fill-opacity:1;stroke-width:0.9562" />
|
||||
<path
|
||||
d="m 13.276586,-84.248473 a 85.332333,85.332333 0 0 1 25.391147,8.2501 L -0.07238066,0.03326978 Z"
|
||||
id="path5791"
|
||||
style="fill:#e7e4c7;fill-opacity:1;stroke-width:0.953434" />
|
||||
</g>
|
||||
<path
|
||||
d="M 16.450001,0 A 16.450001,16.450001 0 1 1 -16.450001,2.0144775e-15 A 16.450001,16.450001 0 1 1 16.450001,-4.0289551e-15 z"
|
||||
id="path5939"
|
||||
style="opacity:1;fill:#00a000;fill-opacity:1;fill-rule:evenodd" />
|
||||
<path
|
||||
d="M 6.9000001,0 A 6.9000001,6.9000001 0 1 1 -6.9000001,8.449784e-16 A 6.9000001,6.9000001 0 1 1 6.9000001,-1.6899568e-15 z"
|
||||
id="path5944"
|
||||
style="opacity:1;fill:#ff0000;fill-opacity:1;fill-rule:evenodd" />
|
||||
</g>
|
||||
<g
|
||||
id="BoardNumbers"
|
||||
style="font-size:28px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;font-family:Sans">
|
||||
<text
|
||||
x="-16.95171"
|
||||
y="-187.82498"
|
||||
id="text6007"
|
||||
xml:space="preserve"><tspan
|
||||
x="-16.95171"
|
||||
y="-187.82498"
|
||||
id="tspan6009">20</tspan></text>
|
||||
<text
|
||||
x="51.872234"
|
||||
y="-180.36624"
|
||||
id="text6895"
|
||||
xml:space="preserve"><tspan
|
||||
x="51.872234"
|
||||
y="-180.36624"
|
||||
id="tspan6897">1</tspan></text>
|
||||
<text
|
||||
x="100.0151"
|
||||
y="-150.53122"
|
||||
id="text6903"
|
||||
xml:space="preserve"><tspan
|
||||
x="100.0151"
|
||||
y="-150.53122"
|
||||
id="tspan6907">18</tspan></text>
|
||||
<text
|
||||
x="153.24347"
|
||||
y="-103.74449"
|
||||
id="text6911"
|
||||
xml:space="preserve"><tspan
|
||||
x="153.24347"
|
||||
y="-103.74449"
|
||||
id="tspan6913">4</tspan></text>
|
||||
<text
|
||||
x="173.92455"
|
||||
y="-45.769642"
|
||||
id="text6915"
|
||||
xml:space="preserve"><tspan
|
||||
x="173.92455"
|
||||
y="-45.769642"
|
||||
id="tspan6917">13</tspan></text>
|
||||
<text
|
||||
x="187.14688"
|
||||
y="9.1538963"
|
||||
id="text6966"
|
||||
xml:space="preserve"><tspan
|
||||
x="187.14688"
|
||||
y="9.1538963"
|
||||
id="tspan6968">6</tspan><tspan
|
||||
x="187.14688"
|
||||
y="37.153896"
|
||||
id="tspan6970" /></text>
|
||||
<text
|
||||
x="171.5513"
|
||||
y="67.467781"
|
||||
id="text6923"
|
||||
xml:space="preserve"><tspan
|
||||
x="171.5513"
|
||||
y="67.467781"
|
||||
id="tspan6925">10</tspan></text>
|
||||
<text
|
||||
x="142.7334"
|
||||
y="127.13781"
|
||||
id="text6927"
|
||||
xml:space="preserve"><tspan
|
||||
x="142.7334"
|
||||
y="127.13781"
|
||||
id="tspan6929">15</tspan></text>
|
||||
<text
|
||||
x="106.11771"
|
||||
y="169.85611"
|
||||
id="text6931"
|
||||
xml:space="preserve"><tspan
|
||||
x="106.11771"
|
||||
y="169.85611"
|
||||
id="tspan6933">2</tspan></text>
|
||||
<text
|
||||
x="42.718311"
|
||||
y="196.63982"
|
||||
id="text6975"
|
||||
xml:space="preserve"><tspan
|
||||
x="42.718311"
|
||||
y="196.63982"
|
||||
id="tspan6977">17</tspan></text>
|
||||
<text
|
||||
x="-6.1026163"
|
||||
y="208.16699"
|
||||
id="text6979"
|
||||
xml:space="preserve"><tspan
|
||||
x="-6.1026163"
|
||||
y="208.16699"
|
||||
id="tspan6981">3</tspan></text>
|
||||
<text
|
||||
x="-74.248497"
|
||||
y="199.01306"
|
||||
id="text6983"
|
||||
xml:space="preserve"><tspan
|
||||
x="-74.248497"
|
||||
y="199.01306"
|
||||
id="tspan6985">19</tspan></text>
|
||||
<text
|
||||
x="-123.74748"
|
||||
y="173.24644"
|
||||
id="text6987"
|
||||
xml:space="preserve"><tspan
|
||||
x="-123.74748"
|
||||
y="173.24644"
|
||||
id="tspan6989">7</tspan></text>
|
||||
<text
|
||||
x="-174.94165"
|
||||
y="127.13781"
|
||||
id="text6991"
|
||||
xml:space="preserve"><tspan
|
||||
x="-174.94165"
|
||||
y="127.13781"
|
||||
id="tspan6993">16</tspan></text>
|
||||
<text
|
||||
x="-193.58855"
|
||||
y="72.892326"
|
||||
id="text6995"
|
||||
xml:space="preserve"><tspan
|
||||
x="-193.58855"
|
||||
y="72.892326"
|
||||
id="tspan6997">8</tspan></text>
|
||||
<text
|
||||
x="-214.60867"
|
||||
y="8.8148642"
|
||||
id="text7011"
|
||||
xml:space="preserve"><tspan
|
||||
x="-214.60867"
|
||||
y="8.8148642"
|
||||
id="tspan7013">11</tspan></text>
|
||||
<text
|
||||
x="-208.50606"
|
||||
y="-48.820953"
|
||||
id="text7015"
|
||||
xml:space="preserve"><tspan
|
||||
x="-208.50606"
|
||||
y="-48.820953"
|
||||
id="tspan7017">14</tspan></text>
|
||||
<text
|
||||
x="-165.10965"
|
||||
y="-109.50809"
|
||||
id="text7019"
|
||||
xml:space="preserve"><tspan
|
||||
x="-165.10965"
|
||||
y="-109.50809"
|
||||
id="tspan7021">9</tspan></text>
|
||||
<text
|
||||
x="-134.25755"
|
||||
y="-152.22639"
|
||||
id="text7023"
|
||||
xml:space="preserve"><tspan
|
||||
x="-134.25755"
|
||||
y="-152.22639"
|
||||
id="tspan7025">12</tspan></text>
|
||||
<text
|
||||
x="-67.467812"
|
||||
y="-178.67107"
|
||||
id="text7027"
|
||||
xml:space="preserve"><tspan
|
||||
x="-67.467812"
|
||||
y="-178.67107"
|
||||
id="tspan7029">5</tspan></text>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 18 KiB |
36
src/components/ui/badge.tsx
Normal file
36
src/components/ui/badge.tsx
Normal file
|
@ -0,0 +1,36 @@
|
|||
import * as React from "react"
|
||||
import { cva, type VariantProps } from "class-variance-authority"
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
|
||||
const badgeVariants = cva(
|
||||
"inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
|
||||
{
|
||||
variants: {
|
||||
variant: {
|
||||
default:
|
||||
"border-transparent bg-primary text-primary-foreground hover:bg-primary/80",
|
||||
secondary:
|
||||
"border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",
|
||||
destructive:
|
||||
"border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80",
|
||||
outline: "text-foreground",
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
variant: "default",
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
export interface BadgeProps
|
||||
extends React.HTMLAttributes<HTMLDivElement>,
|
||||
VariantProps<typeof badgeVariants> {}
|
||||
|
||||
function Badge({ className, variant, ...props }: BadgeProps) {
|
||||
return (
|
||||
<div className={cn(badgeVariants({ variant }), className)} {...props} />
|
||||
)
|
||||
}
|
||||
|
||||
export { Badge, badgeVariants }
|
56
src/components/ui/button.tsx
Normal file
56
src/components/ui/button.tsx
Normal file
|
@ -0,0 +1,56 @@
|
|||
import * as React from "react"
|
||||
import { Slot } from "@radix-ui/react-slot"
|
||||
import { cva, type VariantProps } from "class-variance-authority"
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
|
||||
const buttonVariants = cva(
|
||||
"inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",
|
||||
{
|
||||
variants: {
|
||||
variant: {
|
||||
default: "bg-primary text-primary-foreground hover:bg-primary/90",
|
||||
destructive:
|
||||
"bg-destructive text-destructive-foreground hover:bg-destructive/90",
|
||||
outline:
|
||||
"border border-input bg-background hover:bg-accent hover:text-accent-foreground",
|
||||
secondary:
|
||||
"bg-secondary text-secondary-foreground hover:bg-secondary/80",
|
||||
ghost: "hover:bg-accent hover:text-accent-foreground",
|
||||
link: "text-primary underline-offset-4 hover:underline",
|
||||
},
|
||||
size: {
|
||||
default: "h-10 px-4 py-2",
|
||||
sm: "h-9 rounded-md px-3",
|
||||
lg: "h-11 rounded-md px-8",
|
||||
icon: "h-10 w-10",
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
variant: "default",
|
||||
size: "default",
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
export interface ButtonProps
|
||||
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
|
||||
VariantProps<typeof buttonVariants> {
|
||||
asChild?: boolean
|
||||
}
|
||||
|
||||
const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
|
||||
({ className, variant, size, asChild = false, ...props }, ref) => {
|
||||
const Comp = asChild ? Slot : "button"
|
||||
return (
|
||||
<Comp
|
||||
className={cn(buttonVariants({ variant, size, className }))}
|
||||
ref={ref}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
)
|
||||
Button.displayName = "Button"
|
||||
|
||||
export { Button, buttonVariants }
|
79
src/components/ui/card.tsx
Normal file
79
src/components/ui/card.tsx
Normal file
|
@ -0,0 +1,79 @@
|
|||
import * as React from "react"
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
|
||||
const Card = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
React.HTMLAttributes<HTMLDivElement>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<div
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"rounded-lg border bg-card text-card-foreground shadow-sm",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
Card.displayName = "Card"
|
||||
|
||||
const CardHeader = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
React.HTMLAttributes<HTMLDivElement>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<div
|
||||
ref={ref}
|
||||
className={cn("flex flex-col space-y-1.5 p-6", className)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
CardHeader.displayName = "CardHeader"
|
||||
|
||||
const CardTitle = React.forwardRef<
|
||||
HTMLParagraphElement,
|
||||
React.HTMLAttributes<HTMLHeadingElement>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<h3
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"text-2xl font-semibold leading-none tracking-tight",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
CardTitle.displayName = "CardTitle"
|
||||
|
||||
const CardDescription = React.forwardRef<
|
||||
HTMLParagraphElement,
|
||||
React.HTMLAttributes<HTMLParagraphElement>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<p
|
||||
ref={ref}
|
||||
className={cn("text-sm text-muted-foreground", className)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
CardDescription.displayName = "CardDescription"
|
||||
|
||||
const CardContent = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
React.HTMLAttributes<HTMLDivElement>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<div ref={ref} className={cn("p-6 pt-0", className)} {...props} />
|
||||
))
|
||||
CardContent.displayName = "CardContent"
|
||||
|
||||
const CardFooter = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
React.HTMLAttributes<HTMLDivElement>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<div
|
||||
ref={ref}
|
||||
className={cn("flex items-center p-6 pt-0", className)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
CardFooter.displayName = "CardFooter"
|
||||
|
||||
export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent }
|
25
src/components/ui/input.tsx
Normal file
25
src/components/ui/input.tsx
Normal file
|
@ -0,0 +1,25 @@
|
|||
import * as React from "react"
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
|
||||
export interface InputProps
|
||||
extends React.InputHTMLAttributes<HTMLInputElement> {}
|
||||
|
||||
const Input = React.forwardRef<HTMLInputElement, InputProps>(
|
||||
({ className, type, ...props }, ref) => {
|
||||
return (
|
||||
<input
|
||||
type={type}
|
||||
className={cn(
|
||||
"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
|
||||
className
|
||||
)}
|
||||
ref={ref}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
)
|
||||
Input.displayName = "Input"
|
||||
|
||||
export { Input }
|
24
src/components/ui/label.tsx
Normal file
24
src/components/ui/label.tsx
Normal file
|
@ -0,0 +1,24 @@
|
|||
import * as React from "react"
|
||||
import * as LabelPrimitive from "@radix-ui/react-label"
|
||||
import { cva, type VariantProps } from "class-variance-authority"
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
|
||||
const labelVariants = cva(
|
||||
"text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
|
||||
)
|
||||
|
||||
const Label = React.forwardRef<
|
||||
React.ElementRef<typeof LabelPrimitive.Root>,
|
||||
React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root> &
|
||||
VariantProps<typeof labelVariants>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<LabelPrimitive.Root
|
||||
ref={ref}
|
||||
className={cn(labelVariants(), className)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
Label.displayName = LabelPrimitive.Root.displayName
|
||||
|
||||
export { Label }
|
76
src/index.css
Normal file
76
src/index.css
Normal file
|
@ -0,0 +1,76 @@
|
|||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
@layer base {
|
||||
:root {
|
||||
--background: 0 0% 100%;
|
||||
--foreground: 222.2 84% 4.9%;
|
||||
|
||||
--card: 0 0% 100%;
|
||||
--card-foreground: 222.2 84% 4.9%;
|
||||
|
||||
--popover: 0 0% 100%;
|
||||
--popover-foreground: 222.2 84% 4.9%;
|
||||
|
||||
--primary: 222.2 47.4% 11.2%;
|
||||
--primary-foreground: 210 40% 98%;
|
||||
|
||||
--secondary: 210 40% 96.1%;
|
||||
--secondary-foreground: 222.2 47.4% 11.2%;
|
||||
|
||||
--muted: 210 40% 96.1%;
|
||||
--muted-foreground: 215.4 16.3% 46.9%;
|
||||
|
||||
--accent: 210 40% 96.1%;
|
||||
--accent-foreground: 222.2 47.4% 11.2%;
|
||||
|
||||
--destructive: 0 84.2% 60.2%;
|
||||
--destructive-foreground: 210 40% 98%;
|
||||
|
||||
--border: 214.3 31.8% 91.4%;
|
||||
--input: 214.3 31.8% 91.4%;
|
||||
--ring: 222.2 84% 4.9%;
|
||||
|
||||
--radius: 0.5rem;
|
||||
}
|
||||
|
||||
.dark {
|
||||
--background: 222.2 84% 4.9%;
|
||||
--foreground: 210 40% 98%;
|
||||
|
||||
--card: 222.2 84% 4.9%;
|
||||
--card-foreground: 210 40% 98%;
|
||||
|
||||
--popover: 222.2 84% 4.9%;
|
||||
--popover-foreground: 210 40% 98%;
|
||||
|
||||
--primary: 210 40% 98%;
|
||||
--primary-foreground: 222.2 47.4% 11.2%;
|
||||
|
||||
--secondary: 217.2 32.6% 17.5%;
|
||||
--secondary-foreground: 210 40% 98%;
|
||||
|
||||
--muted: 217.2 32.6% 17.5%;
|
||||
--muted-foreground: 215 20.2% 65.1%;
|
||||
|
||||
--accent: 217.2 32.6% 17.5%;
|
||||
--accent-foreground: 210 40% 98%;
|
||||
|
||||
--destructive: 0 62.8% 30.6%;
|
||||
--destructive-foreground: 210 40% 98%;
|
||||
|
||||
--border: 217.2 32.6% 17.5%;
|
||||
--input: 217.2 32.6% 17.5%;
|
||||
--ring: 212.7 26.8% 83.9%;
|
||||
}
|
||||
}
|
||||
|
||||
@layer base {
|
||||
* {
|
||||
@apply border-border;
|
||||
}
|
||||
body {
|
||||
@apply bg-background text-foreground;
|
||||
}
|
||||
}
|
6
src/lib/utils.ts
Normal file
6
src/lib/utils.ts
Normal file
|
@ -0,0 +1,6 @@
|
|||
import { type ClassValue, clsx } from "clsx"
|
||||
import { twMerge } from "tailwind-merge"
|
||||
|
||||
export function cn(...inputs: ClassValue[]) {
|
||||
return twMerge(clsx(inputs))
|
||||
}
|
10
src/main.tsx
Normal file
10
src/main.tsx
Normal file
|
@ -0,0 +1,10 @@
|
|||
import React from 'react'
|
||||
import ReactDOM from 'react-dom/client'
|
||||
import App from './App.tsx'
|
||||
import './index.css'
|
||||
|
||||
ReactDOM.createRoot(document.getElementById('root')!).render(
|
||||
<React.StrictMode>
|
||||
<App />
|
||||
</React.StrictMode>,
|
||||
)
|
1
src/vite-env.d.ts
vendored
Normal file
1
src/vite-env.d.ts
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
/// <reference types="vite/client" />
|
80
tailwind.config.ts
Normal file
80
tailwind.config.ts
Normal file
|
@ -0,0 +1,80 @@
|
|||
import type { Config } from "tailwindcss"
|
||||
|
||||
const config = {
|
||||
darkMode: ["class"],
|
||||
content: [
|
||||
'./pages/**/*.{ts,tsx}',
|
||||
'./components/**/*.{ts,tsx}',
|
||||
'./app/**/*.{ts,tsx}',
|
||||
'./src/**/*.{ts,tsx}',
|
||||
],
|
||||
prefix: "",
|
||||
theme: {
|
||||
container: {
|
||||
center: true,
|
||||
padding: "2rem",
|
||||
screens: {
|
||||
"2xl": "1400px",
|
||||
},
|
||||
},
|
||||
extend: {
|
||||
colors: {
|
||||
border: "hsl(var(--border))",
|
||||
input: "hsl(var(--input))",
|
||||
ring: "hsl(var(--ring))",
|
||||
background: "hsl(var(--background))",
|
||||
foreground: "hsl(var(--foreground))",
|
||||
primary: {
|
||||
DEFAULT: "hsl(var(--primary))",
|
||||
foreground: "hsl(var(--primary-foreground))",
|
||||
},
|
||||
secondary: {
|
||||
DEFAULT: "hsl(var(--secondary))",
|
||||
foreground: "hsl(var(--secondary-foreground))",
|
||||
},
|
||||
destructive: {
|
||||
DEFAULT: "hsl(var(--destructive))",
|
||||
foreground: "hsl(var(--destructive-foreground))",
|
||||
},
|
||||
muted: {
|
||||
DEFAULT: "hsl(var(--muted))",
|
||||
foreground: "hsl(var(--muted-foreground))",
|
||||
},
|
||||
accent: {
|
||||
DEFAULT: "hsl(var(--accent))",
|
||||
foreground: "hsl(var(--accent-foreground))",
|
||||
},
|
||||
popover: {
|
||||
DEFAULT: "hsl(var(--popover))",
|
||||
foreground: "hsl(var(--popover-foreground))",
|
||||
},
|
||||
card: {
|
||||
DEFAULT: "hsl(var(--card))",
|
||||
foreground: "hsl(var(--card-foreground))",
|
||||
},
|
||||
},
|
||||
borderRadius: {
|
||||
lg: "var(--radius)",
|
||||
md: "calc(var(--radius) - 2px)",
|
||||
sm: "calc(var(--radius) - 4px)",
|
||||
},
|
||||
keyframes: {
|
||||
"accordion-down": {
|
||||
from: { height: "0" },
|
||||
to: { height: "var(--radix-accordion-content-height)" },
|
||||
},
|
||||
"accordion-up": {
|
||||
from: { height: "var(--radix-accordion-content-height)" },
|
||||
to: { height: "0" },
|
||||
},
|
||||
},
|
||||
animation: {
|
||||
"accordion-down": "accordion-down 0.2s ease-out",
|
||||
"accordion-up": "accordion-up 0.2s ease-out",
|
||||
},
|
||||
},
|
||||
},
|
||||
plugins: [require("tailwindcss-animate")],
|
||||
} satisfies Config
|
||||
|
||||
export default config
|
27
tsconfig.app.json
Normal file
27
tsconfig.app.json
Normal file
|
@ -0,0 +1,27 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"composite": true,
|
||||
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
|
||||
"target": "ES2020",
|
||||
"useDefineForClassFields": true,
|
||||
"lib": ["ES2020", "DOM", "DOM.Iterable"],
|
||||
"module": "ESNext",
|
||||
"skipLibCheck": true,
|
||||
|
||||
/* Bundler mode */
|
||||
"moduleResolution": "bundler",
|
||||
"allowImportingTsExtensions": true,
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"moduleDetection": "force",
|
||||
"noEmit": true,
|
||||
"jsx": "react-jsx",
|
||||
|
||||
/* Linting */
|
||||
"strict": true,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"noFallthroughCasesInSwitch": true
|
||||
},
|
||||
"include": ["src"]
|
||||
}
|
19
tsconfig.json
Normal file
19
tsconfig.json
Normal file
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"files": [],
|
||||
"compilerOptions": {
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"@/*": [
|
||||
"./src/*"
|
||||
]
|
||||
},
|
||||
},
|
||||
"references": [
|
||||
{
|
||||
"path": "./tsconfig.app.json"
|
||||
},
|
||||
{
|
||||
"path": "./tsconfig.node.json"
|
||||
}
|
||||
]
|
||||
}
|
13
tsconfig.node.json
Normal file
13
tsconfig.node.json
Normal file
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"composite": true,
|
||||
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
|
||||
"skipLibCheck": true,
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "bundler",
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"strict": true,
|
||||
"noEmit": true
|
||||
},
|
||||
"include": ["vite.config.ts"]
|
||||
}
|
15
vite.config.ts
Normal file
15
vite.config.ts
Normal file
|
@ -0,0 +1,15 @@
|
|||
import { defineConfig } from 'vite'
|
||||
import react from '@vitejs/plugin-react-swc'
|
||||
// @ts-ignore
|
||||
import path from 'path'
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig({
|
||||
plugins: [react()],
|
||||
resolve: {
|
||||
alias: {
|
||||
// @ts-ignore
|
||||
"@": path.resolve(__dirname, "./src"),
|
||||
},
|
||||
},
|
||||
})
|
Loading…
Reference in a new issue