feat: add missing fields to Edit Dialog

Extend dialog to include secret, algorithm, digits, and period for full editing.

Co-authored-by: Simon <85533298+handsomezhuzhu@users.noreply.github.com>
This commit is contained in:
v0
2026-02-04 15:10:54 +00:00
parent bad93bb877
commit b0aa34da7b
17 changed files with 815 additions and 844 deletions

View File

@@ -1,59 +1,30 @@
# Frontend 2FA Tool # Frontend 2FA tool
这是一个安全、离线优先的前端双因素认证 (2FA) 工具,基于 Next.js 构建。 *Automatically synced with your [v0.app](https://v0.app) deployments*
## 功能特性 [![Deployed on Vercel](https://img.shields.io/badge/Deployed%20on-Vercel-black?style=for-the-badge&logo=vercel)](https://vercel.com/kdaugh14-4907s-projects/v0-frontend-2-fa-tool)
[![Built with v0](https://img.shields.io/badge/Built%20with-v0.app-black?style=for-the-badge)](https://v0.app/chat/cHtdgE8H6EW)
- 🔒 **安全**: 所有数据存储在本地,不上传服务器 ## Overview
- 📱 **QR 扫码**: 支持直接扫描 QR 码添加令牌 (使用 jsQR)
- ⌨️ **手动录入**: 支持手动输入密钥添加
- 🌓 **深色模式**: 内置明亮/深色主题切换
- 📤 **导入/导出**: 支持令牌数据的备份与恢复
- 🌐 **多语言**: 支持国际化
## 技术栈 This repository will stay in sync with your deployed chats on [v0.app](https://v0.app).
Any changes you make to your deployed app will be automatically pushed to this repository from [v0.app](https://v0.app).
- **框架**: Next.js 14 ## Deployment
- **UI 组件**: Radix UI
- **样式**: Tailwind CSS
- **工具库**: jsQR, date-fns
## 环境变量 Your project is live at:
可以在部署时设置以下环境变量来配置页脚信息: **[https://vercel.com/kdaugh14-4907s-projects/v0-frontend-2-fa-tool](https://vercel.com/kdaugh14-4907s-projects/v0-frontend-2-fa-tool)**
- `NEXT_PUBLIC_SHOW_FOOTER`: 是否显示页脚 (默认: true, 设置为 "false" 隐藏) ## Build your app
- `NEXT_PUBLIC_FILING_ICP`: ICP 备案号 (例如: 滇ICP备xxxxxxxx号)
- `NEXT_PUBLIC_FILING_SECURITY`: 公安联网备案号 (例如: 滇公网安备xxxxxxxxxxxxxx号)
## 声明 Continue building your app on:
本项目由阿里云ESA提供加速、计算和保护 **[https://v0.app/chat/cHtdgE8H6EW](https://v0.app/chat/cHtdgE8H6EW)**
![阿里云ESA Pages](public/images/aliyun-esa.png) ## How It Works
## 开始使用 1. Create and modify your project using [v0.app](https://v0.app)
2. Deploy your chats from the v0 interface
1. 安装依赖: 3. Changes are automatically pushed to this repository
4. Vercel deploys the latest version from this repository
```bash
pnpm install
```
2. 启动开发服务器:
```bash
pnpm dev
```
3. 访问 [http://localhost:3000](http://localhost:3000)
## 构建
```bash
pnpm build
```
## 部署
本项目可以直接部署在阿里云 ESA Pages 上。

View File

@@ -19,7 +19,7 @@
--accent: oklch(0.97 0 0); --accent: oklch(0.97 0 0);
--accent-foreground: oklch(0.205 0 0); --accent-foreground: oklch(0.205 0 0);
--destructive: oklch(0.577 0.245 27.325); --destructive: oklch(0.577 0.245 27.325);
--destructive-foreground: oklch(0.985 0 0); --destructive-foreground: oklch(0.577 0.245 27.325);
--border: oklch(0.922 0 0); --border: oklch(0.922 0 0);
--input: oklch(0.922 0 0); --input: oklch(0.922 0 0);
--ring: oklch(0.708 0 0); --ring: oklch(0.708 0 0);

View File

@@ -27,7 +27,6 @@ import {
Monitor, Monitor,
Languages, Languages,
Check, Check,
Github,
} from "lucide-react" } from "lucide-react"
import { Button } from "@/components/ui/button" import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input" import { Input } from "@/components/ui/input"
@@ -163,7 +162,6 @@ export default function TwoFactorAuth() {
const [isSettingsOpen, setIsSettingsOpen] = useState(false) const [isSettingsOpen, setIsSettingsOpen] = useState(false)
const [editingToken, setEditingToken] = useState<TOTPToken | null>(null) const [editingToken, setEditingToken] = useState<TOTPToken | null>(null)
const [showAdvanced, setShowAdvanced] = useState(false) const [showAdvanced, setShowAdvanced] = useState(false)
const [mounted, setMounted] = useState(false)
const videoRef = useRef<HTMLVideoElement>(null) const videoRef = useRef<HTMLVideoElement>(null)
const canvasRef = useRef<HTMLCanvasElement>(null) const canvasRef = useRef<HTMLCanvasElement>(null)
const fileInputRef = useRef<HTMLInputElement>(null) const fileInputRef = useRef<HTMLInputElement>(null)
@@ -197,7 +195,6 @@ export default function TwoFactorAuth() {
if (savedSettings) { if (savedSettings) {
setSettings(JSON.parse(savedSettings)) setSettings(JSON.parse(savedSettings))
} }
setMounted(true)
}, []) }, [])
// Save tokens to localStorage // Save tokens to localStorage
@@ -658,33 +655,15 @@ export default function TwoFactorAuth() {
</div> </div>
</div> </div>
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<Button variant="ghost" size="icon" asChild>
<a
href="https://github.com/handsomezhuzhu/2fa-tool"
target="_blank"
rel="noopener noreferrer"
title="GitHub"
>
<Github className="h-5 w-5" />
<span className="sr-only">GitHub</span>
</a>
</Button>
<Button <Button
variant="ghost" variant="ghost"
size="icon" size="icon"
onClick={cycleTheme} onClick={cycleTheme}
title={mounted ? (theme === "light" ? t.themeLight : theme === "dark" ? t.themeDark : t.themeSystem) : t.themeSystem} title={theme === "light" ? t.themeLight : theme === "dark" ? t.themeDark : t.themeSystem}
> >
{!mounted ? ( {theme === "light" && <Sun className="h-5 w-5" />}
<Monitor className="h-5 w-5" /> {theme === "dark" && <Moon className="h-5 w-5" />}
) : ( {theme === "system" && <Monitor className="h-5 w-5" />}
<>
{theme === "light" && <Sun className="h-5 w-5" />}
{theme === "dark" && <Moon className="h-5 w-5" />}
{theme === "system" && <Monitor className="h-5 w-5" />}
</>
)}
<span className="sr-only">Toggle theme</span> <span className="sr-only">Toggle theme</span>
</Button> </Button>
@@ -1017,7 +996,7 @@ export default function TwoFactorAuth() {
{/* Edit Dialog */} {/* Edit Dialog */}
<Dialog open={!!editingToken} onOpenChange={(open) => !open && setEditingToken(null)}> <Dialog open={!!editingToken} onOpenChange={(open) => !open && setEditingToken(null)}>
<DialogContent> <DialogContent className="max-h-[90vh] overflow-y-auto">
<DialogHeader> <DialogHeader>
<DialogTitle>{t.editToken}</DialogTitle> <DialogTitle>{t.editToken}</DialogTitle>
</DialogHeader> </DialogHeader>
@@ -1037,6 +1016,68 @@ export default function TwoFactorAuth() {
onChange={(e) => setEditingToken({ ...editingToken, issuer: e.target.value })} onChange={(e) => setEditingToken({ ...editingToken, issuer: e.target.value })}
/> />
</div> </div>
<div className="space-y-2">
<Label>{t.secretKey}</Label>
<Input
value={editingToken.secret}
onChange={(e) => setEditingToken({ ...editingToken, secret: e.target.value.toUpperCase().replace(/\s/g, "") })}
className="font-mono"
/>
</div>
<div className="grid grid-cols-3 gap-4">
<div className="space-y-2">
<Label>{t.algorithm}</Label>
<Select
value={editingToken.algorithm}
onValueChange={(value: "SHA1" | "SHA256" | "SHA512") =>
setEditingToken({ ...editingToken, algorithm: value })
}
>
<SelectTrigger>
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="SHA1">SHA-1</SelectItem>
<SelectItem value="SHA256">SHA-256</SelectItem>
<SelectItem value="SHA512">SHA-512</SelectItem>
</SelectContent>
</Select>
</div>
<div className="space-y-2">
<Label>{t.digits}</Label>
<Select
value={editingToken.digits.toString()}
onValueChange={(value) =>
setEditingToken({ ...editingToken, digits: parseInt(value) as 6 | 8 })
}
>
<SelectTrigger>
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="6">6</SelectItem>
<SelectItem value="8">8</SelectItem>
</SelectContent>
</Select>
</div>
<div className="space-y-2">
<Label>{t.period}</Label>
<Select
value={editingToken.period.toString()}
onValueChange={(value) =>
setEditingToken({ ...editingToken, period: parseInt(value) })
}
>
<SelectTrigger>
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="30">30s</SelectItem>
<SelectItem value="60">60s</SelectItem>
</SelectContent>
</Select>
</div>
</div>
</div> </div>
)} )}
<DialogFooter> <DialogFooter>
@@ -1049,50 +1090,39 @@ export default function TwoFactorAuth() {
</Dialog> </Dialog>
{/* Footer */} {/* Footer */}
{/* Footer */} <footer className="border-t py-6 mt-auto">
{(process.env.NEXT_PUBLIC_SHOW_FOOTER !== "false") && ( <div className="mx-auto flex max-w-4xl flex-col items-center gap-2 text-center md:flex-row md:justify-between md:gap-4 px-4">
<footer className="border-t py-6 mt-auto"> <p className="text-xs tracking-wider text-muted-foreground">© 2025 Simon. All rights reserved.</p>
<div className="mx-auto flex max-w-4xl flex-col items-center gap-2 text-center md:flex-row md:justify-between md:gap-4 px-4"> <div className="flex items-center gap-4 text-xs tracking-wider text-muted-foreground/60">
<p className="text-xs tracking-wider text-muted-foreground">© 2025 Simon. All rights reserved.</p> <a
{(process.env.NEXT_PUBLIC_FILING_ICP || process.env.NEXT_PUBLIC_FILING_SECURITY) && ( href="https://beian.miit.gov.cn/"
<div className="flex items-center gap-4 text-xs tracking-wider text-muted-foreground/60"> target="_blank"
{process.env.NEXT_PUBLIC_FILING_ICP && ( rel="noopener noreferrer"
<a className="transition-colors hover:text-muted-foreground"
href="https://beian.miit.gov.cn/" >
target="_blank" ICP备2025074424号
rel="noopener noreferrer" </a>
className="transition-colors hover:text-muted-foreground" <span className="text-muted-foreground/30">|</span>
> <a
{process.env.NEXT_PUBLIC_FILING_ICP} href="https://beian.mps.gov.cn"
</a> target="_blank"
)} rel="noopener noreferrer"
{process.env.NEXT_PUBLIC_FILING_ICP && process.env.NEXT_PUBLIC_FILING_SECURITY && ( className="flex items-center gap-1.5 transition-colors hover:text-muted-foreground"
<span className="text-muted-foreground/30">|</span> >
)} <img
{process.env.NEXT_PUBLIC_FILING_SECURITY && ( alt="公安备案"
<a loading="lazy"
href="https://beian.mps.gov.cn" width="14"
target="_blank" height="14"
rel="noopener noreferrer" decoding="async"
className="flex items-center gap-1.5 transition-colors hover:text-muted-foreground" className="opacity-60"
> src="/images/beian.png"
<img />
alt="公安备案" 53250402000233
loading="lazy" </a>
width="14"
height="14"
decoding="async"
className="opacity-60"
src="/images/beian.png"
/>
{process.env.NEXT_PUBLIC_FILING_SECURITY}
</a>
)}
</div>
)}
</div> </div>
</footer> </div>
)} </footer>
<Toaster /> <Toaster />
</div> </div>
@@ -1168,8 +1198,9 @@ function TokenCard({ token, code, timeLeft, showCode, onCopy, onEdit, onDelete,
</button> </button>
<span <span
className={`font-mono text-base font-bold min-w-[90px] text-center transition-colors ${copied ? "text-green-500" : "" className={`font-mono text-base font-bold min-w-[90px] text-center transition-colors ${
}`} copied ? "text-green-500" : ""
}`}
> >
{visible ? formattedCode : "••• •••"} {visible ? formattedCode : "••• •••"}
</span> </span>

View File

@@ -77,7 +77,7 @@ const ToastClose = React.forwardRef<
<ToastPrimitives.Close <ToastPrimitives.Close
ref={ref} ref={ref}
className={cn( className={cn(
'absolute right-2 top-2 rounded-md p-1 text-foreground/50 transition-opacity hover:text-foreground focus:opacity-100 focus:outline-none focus:ring-2 group-hover:opacity-100 group-[.destructive]:text-red-300 group-[.destructive]:hover:text-red-50 group-[.destructive]:focus:ring-red-400 group-[.destructive]:focus:ring-offset-red-600', 'absolute right-2 top-2 rounded-md p-1 text-foreground/50 opacity-0 transition-opacity hover:text-foreground focus:opacity-100 focus:outline-none focus:ring-2 group-hover:opacity-100 group-[.destructive]:text-red-300 group-[.destructive]:hover:text-red-50 group-[.destructive]:focus:ring-red-400 group-[.destructive]:focus:ring-offset-red-600',
className, className,
)} )}
toast-close="" toast-close=""

View File

@@ -69,6 +69,6 @@
"postcss": "^8.5", "postcss": "^8.5",
"tailwindcss": "^4.1.9", "tailwindcss": "^4.1.9",
"tw-animate-css": "1.3.3", "tw-animate-css": "1.3.3",
"typescript": "^5.9.3" "typescript": "^5"
} }
} }

1363
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

BIN
public/apple-icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

BIN
public/icon-dark-32x32.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 585 B

BIN
public/icon-light-32x32.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 566 B

26
public/icon.svg Normal file
View File

@@ -0,0 +1,26 @@
<svg width="180" height="180" viewBox="0 0 180 180" fill="none" xmlns="http://www.w3.org/2000/svg">
<style>
@media (prefers-color-scheme: light) {
.background { fill: black; }
.foreground { fill: white; }
}
@media (prefers-color-scheme: dark) {
.background { fill: white; }
.foreground { fill: black; }
}
</style>
<g clip-path="url(#clip0_7960_43945)">
<rect class="background" width="180" height="180" rx="37" />
<g style="transform: scale(95%); transform-origin: center">
<path class="foreground"
d="M101.141 53H136.632C151.023 53 162.689 64.6662 162.689 79.0573V112.904H148.112V79.0573C148.112 78.7105 148.098 78.3662 148.072 78.0251L112.581 112.898C112.701 112.902 112.821 112.904 112.941 112.904H148.112V126.672H112.941C98.5504 126.672 86.5638 114.891 86.5638 100.5V66.7434H101.141V100.5C101.141 101.15 101.191 101.792 101.289 102.422L137.56 66.7816C137.255 66.7563 136.945 66.7434 136.632 66.7434H101.141V53Z" />
<path class="foreground"
d="M65.2926 124.136L14 66.7372H34.6355L64.7495 100.436V66.7372H80.1365V118.47C80.1365 126.278 70.4953 129.958 65.2926 124.136Z" />
</g>
</g>
<defs>
<clipPath id="clip0_7960_43945">
<rect width="180" height="180" fill="white" />
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 119 KiB

BIN
public/placeholder-logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 568 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="215" height="48" fill="none"><path fill="#000" d="M57.588 9.6h6L73.828 38h-5.2l-2.36-6.88h-11.36L52.548 38h-5.2l10.24-28.4Zm7.16 17.16-4.16-12.16-4.16 12.16h8.32Zm23.694-2.24c-.186-1.307-.706-2.32-1.56-3.04-.853-.72-1.866-1.08-3.04-1.08-1.68 0-2.986.613-3.92 1.84-.906 1.227-1.36 2.947-1.36 5.16s.454 3.933 1.36 5.16c.934 1.227 2.24 1.84 3.92 1.84 1.254 0 2.307-.373 3.16-1.12.854-.773 1.387-1.867 1.6-3.28l5.12.24c-.186 1.68-.733 3.147-1.64 4.4-.906 1.227-2.08 2.173-3.52 2.84-1.413.667-2.986 1-4.72 1-2.08 0-3.906-.453-5.48-1.36-1.546-.907-2.76-2.2-3.64-3.88-.853-1.68-1.28-3.627-1.28-5.84 0-2.24.427-4.187 1.28-5.84.88-1.68 2.094-2.973 3.64-3.88 1.574-.907 3.4-1.36 5.48-1.36 1.68 0 3.227.32 4.64.96 1.414.64 2.56 1.56 3.44 2.76.907 1.2 1.454 2.6 1.64 4.2l-5.12.28Zm11.486-7.72.12 3.4c.534-1.227 1.307-2.173 2.32-2.84 1.04-.693 2.267-1.04 3.68-1.04 1.494 0 2.76.387 3.8 1.16 1.067.747 1.827 1.813 2.28 3.2.507-1.44 1.294-2.52 2.36-3.24 1.094-.747 2.414-1.12 3.96-1.12 1.414 0 2.64.307 3.68.92s1.84 1.52 2.4 2.72c.56 1.2.84 2.667.84 4.4V38h-4.96V25.92c0-1.813-.293-3.187-.88-4.12-.56-.96-1.413-1.44-2.56-1.44-.906 0-1.68.213-2.32.64-.64.427-1.133 1.053-1.48 1.88-.32.827-.48 1.84-.48 3.04V38h-4.56V25.92c0-1.2-.133-2.213-.4-3.04-.24-.827-.626-1.453-1.16-1.88-.506-.427-1.133-.64-1.88-.64-.906 0-1.68.227-2.32.68-.64.427-1.133 1.053-1.48 1.88-.32.827-.48 1.827-.48 3V38h-4.96V16.8h4.48Zm26.723 10.6c0-2.24.427-4.187 1.28-5.84.854-1.68 2.067-2.973 3.64-3.88 1.574-.907 3.4-1.36 5.48-1.36 1.84 0 3.494.413 4.96 1.24 1.467.827 2.64 2.08 3.52 3.76.88 1.653 1.347 3.693 1.4 6.12v1.32h-15.08c.107 1.813.614 3.227 1.52 4.24.907.987 2.134 1.48 3.68 1.48.987 0 1.88-.253 2.68-.76a4.803 4.803 0 0 0 1.84-2.2l5.08.36c-.64 2.027-1.84 3.64-3.6 4.84-1.733 1.173-3.733 1.76-6 1.76-2.08 0-3.906-.453-5.48-1.36-1.573-.907-2.786-2.2-3.64-3.88-.853-1.68-1.28-3.627-1.28-5.84Zm15.16-2.04c-.213-1.733-.76-3.013-1.64-3.84-.853-.827-1.893-1.24-3.12-1.24-1.44 0-2.6.453-3.48 1.36-.88.88-1.44 2.12-1.68 3.72h9.92ZM163.139 9.6V38h-5.04V9.6h5.04Zm8.322 7.2.24 5.88-.64-.36c.32-2.053 1.094-3.56 2.32-4.52 1.254-.987 2.787-1.48 4.6-1.48 2.32 0 4.107.733 5.36 2.2 1.254 1.44 1.88 3.387 1.88 5.84V38h-4.96V25.92c0-1.253-.12-2.28-.36-3.08-.24-.8-.64-1.413-1.2-1.84-.533-.427-1.253-.64-2.16-.64-1.44 0-2.573.48-3.4 1.44-.8.933-1.2 2.307-1.2 4.12V38h-4.96V16.8h4.48Zm30.003 7.72c-.186-1.307-.706-2.32-1.56-3.04-.853-.72-1.866-1.08-3.04-1.08-1.68 0-2.986.613-3.92 1.84-.906 1.227-1.36 2.947-1.36 5.16s.454 3.933 1.36 5.16c.934 1.227 2.24 1.84 3.92 1.84 1.254 0 2.307-.373 3.16-1.12.854-.773 1.387-1.867 1.6-3.28l5.12.24c-.186 1.68-.733 3.147-1.64 4.4-.906 1.227-2.08 2.173-3.52 2.84-1.413.667-2.986 1-4.72 1-2.08 0-3.906-.453-5.48-1.36-1.546-.907-2.76-2.2-3.64-3.88-.853-1.68-1.28-3.627-1.28-5.84 0-2.24.427-4.187 1.28-5.84.88-1.68 2.094-2.973 3.64-3.88 1.574-.907 3.4-1.36 5.48-1.36 1.68 0 3.227.32 4.64.96 1.414.64 2.56 1.56 3.44 2.76.907 1.2 1.454 2.6 1.64 4.2l-5.12.28Zm11.443 8.16V38h-5.6v-5.32h5.6Z"/><path fill="#171717" fill-rule="evenodd" d="m7.839 40.783 16.03-28.054L20 6 0 40.783h7.839Zm8.214 0H40L27.99 19.894l-4.02 7.032 3.976 6.914H20.02l-3.967 6.943Z" clip-rule="evenodd"/></svg>

After

Width:  |  Height:  |  Size: 3.1 KiB

BIN
public/placeholder-user.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

BIN
public/placeholder.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

1
public/placeholder.svg Normal file
View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="1200" height="1200" fill="none"><rect width="1200" height="1200" fill="#EAEAEA" rx="3"/><g opacity=".5"><g opacity=".5"><path fill="#FAFAFA" d="M600.709 736.5c-75.454 0-136.621-61.167-136.621-136.62 0-75.454 61.167-136.621 136.621-136.621 75.453 0 136.62 61.167 136.62 136.621 0 75.453-61.167 136.62-136.62 136.62Z"/><path stroke="#C9C9C9" stroke-width="2.418" d="M600.709 736.5c-75.454 0-136.621-61.167-136.621-136.62 0-75.454 61.167-136.621 136.621-136.621 75.453 0 136.62 61.167 136.62 136.621 0 75.453-61.167 136.62-136.62 136.62Z"/></g><path stroke="url(#a)" stroke-width="2.418" d="M0-1.209h553.581" transform="scale(1 -1) rotate(45 1163.11 91.165)"/><path stroke="url(#b)" stroke-width="2.418" d="M404.846 598.671h391.726"/><path stroke="url(#c)" stroke-width="2.418" d="M599.5 795.742V404.017"/><path stroke="url(#d)" stroke-width="2.418" d="m795.717 796.597-391.441-391.44"/><path fill="#fff" d="M600.709 656.704c-31.384 0-56.825-25.441-56.825-56.824 0-31.384 25.441-56.825 56.825-56.825 31.383 0 56.824 25.441 56.824 56.825 0 31.383-25.441 56.824-56.824 56.824Z"/><g clip-path="url(#e)"><path fill="#666" fill-rule="evenodd" d="M616.426 586.58h-31.434v16.176l3.553-3.554.531-.531h9.068l.074-.074 8.463-8.463h2.565l7.18 7.181V586.58Zm-15.715 14.654 3.698 3.699 1.283 1.282-2.565 2.565-1.282-1.283-5.2-5.199h-6.066l-5.514 5.514-.073.073v2.876a2.418 2.418 0 0 0 2.418 2.418h26.598a2.418 2.418 0 0 0 2.418-2.418v-8.317l-8.463-8.463-7.181 7.181-.071.072Zm-19.347 5.442v4.085a6.045 6.045 0 0 0 6.046 6.045h26.598a6.044 6.044 0 0 0 6.045-6.045v-7.108l1.356-1.355-1.282-1.283-.074-.073v-17.989h-38.689v23.43l-.146.146.146.147Z" clip-rule="evenodd"/></g><path stroke="#C9C9C9" stroke-width="2.418" d="M600.709 656.704c-31.384 0-56.825-25.441-56.825-56.824 0-31.384 25.441-56.825 56.825-56.825 31.383 0 56.824 25.441 56.824 56.825 0 31.383-25.441 56.824-56.824 56.824Z"/></g><defs><linearGradient id="a" x1="554.061" x2="-.48" y1=".083" y2=".087" gradientUnits="userSpaceOnUse"><stop stop-color="#C9C9C9" stop-opacity="0"/><stop offset=".208" stop-color="#C9C9C9"/><stop offset=".792" stop-color="#C9C9C9"/><stop offset="1" stop-color="#C9C9C9" stop-opacity="0"/></linearGradient><linearGradient id="b" x1="796.912" x2="404.507" y1="599.963" y2="599.965" gradientUnits="userSpaceOnUse"><stop stop-color="#C9C9C9" stop-opacity="0"/><stop offset=".208" stop-color="#C9C9C9"/><stop offset=".792" stop-color="#C9C9C9"/><stop offset="1" stop-color="#C9C9C9" stop-opacity="0"/></linearGradient><linearGradient id="c" x1="600.792" x2="600.794" y1="403.677" y2="796.082" gradientUnits="userSpaceOnUse"><stop stop-color="#C9C9C9" stop-opacity="0"/><stop offset=".208" stop-color="#C9C9C9"/><stop offset=".792" stop-color="#C9C9C9"/><stop offset="1" stop-color="#C9C9C9" stop-opacity="0"/></linearGradient><linearGradient id="d" x1="404.85" x2="796.972" y1="403.903" y2="796.02" gradientUnits="userSpaceOnUse"><stop stop-color="#C9C9C9" stop-opacity="0"/><stop offset=".208" stop-color="#C9C9C9"/><stop offset=".792" stop-color="#C9C9C9"/><stop offset="1" stop-color="#C9C9C9" stop-opacity="0"/></linearGradient><clipPath id="e"><path fill="#fff" d="M581.364 580.535h38.689v38.689h-38.689z"/></clipPath></defs></svg>

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

@@ -1,10 +1,6 @@
{ {
"compilerOptions": { "compilerOptions": {
"lib": [ "lib": ["dom", "dom.iterable", "esnext"],
"dom",
"dom.iterable",
"esnext"
],
"allowJs": true, "allowJs": true,
"target": "ES6", "target": "ES6",
"skipLibCheck": true, "skipLibCheck": true,
@@ -15,7 +11,7 @@
"moduleResolution": "bundler", "moduleResolution": "bundler",
"resolveJsonModule": true, "resolveJsonModule": true,
"isolatedModules": true, "isolatedModules": true,
"jsx": "react-jsx", "jsx": "preserve",
"incremental": true, "incremental": true,
"plugins": [ "plugins": [
{ {
@@ -23,19 +19,9 @@
} }
], ],
"paths": { "paths": {
"@/*": [ "@/*": ["./*"]
"./*"
]
} }
}, },
"include": [ "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
"next-env.d.ts", "exclude": ["node_modules"]
"**/*.ts",
"**/*.tsx",
".next/types/**/*.ts",
".next/dev/types/**/*.ts"
],
"exclude": [
"node_modules"
]
} }