refactor: reorganize directory structure into src/

Move all source code directories into src/ for cleaner project structure:
- pages/, components/, utils/, config/, providers/, types/, lib/, assets/, entrypoints/ → src/
- Use WXT srcDir config to resolve @/ alias to src/
- Update tsconfig, vitest, eslint, tailwind configs
- Remove scattered README.md files from subdirectories
- Update documentation (AGENTS.md, CODING_STANDARDS.md, README.md)
- Fix pre-existing lint error in RouterProvider.tsx

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
雨霖铃
2026-05-28 20:20:45 +08:00
parent 9903483f42
commit b79fe7dd49
166 changed files with 86 additions and 631 deletions
+71
View File
@@ -0,0 +1,71 @@
import React from 'react';
import { cn } from '@/lib/utils'; // 1. 引入标准的 shadcn 工具函数
export interface SwitchOption<T extends string | number = string> {
value: T;
label: React.ReactNode;
}
// 2. 移除内联 sx,继承标准 HTML 属性,并使用标准的类名注入机制
export interface SwitchButtonGroupProps<T extends string | number = string> extends Omit<
React.HTMLAttributes<HTMLDivElement>,
'onChange'
> {
value: T;
options: SwitchOption<T>[];
onChange: (value: T) => void;
size?: 'small' | 'medium' | 'large';
buttonClassName?: string; // 替换原有的 buttonSx
}
export default function SwitchButtonGroup<T extends string | number = string>({
value,
options,
onChange,
size = 'medium',
className,
buttonClassName,
...props
}: SwitchButtonGroupProps<T>) {
// 3. 将尺寸和高度、内边距等整体对齐,保证按钮和背景容器成比例缩放
const sizeClasses = {
small: 'text-xs h-8 px-2 py-1 rounded-md',
medium: 'text-sm h-9 px-3 py-1.5 rounded-md',
large: 'text-base h-11 px-4 py-2 rounded-lg',
};
return (
<div
className={cn(
'inline-flex w-full items-center justify-center rounded-lg bg-muted text-muted-foreground p-1',
className,
)}
{...props}
>
{options.map((option) => {
const isSelected = value === option.value;
return (
<button
key={option.value}
type="button"
onClick={() => onChange(option.value)}
className={cn(
// 4. 完美继承 shadcn 的 Tabs 交互和动效微调
'flex-1 inline-flex items-center justify-center font-medium whitespace-nowrap transition-all',
'focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring focus-visible:ring-offset-2',
'disabled:pointer-events-none disabled:opacity-50',
sizeClasses[size],
isSelected
? 'bg-background text-foreground shadow-sm font-semibold animate-in fade-in-50 zoom-in-95 duration-150'
: 'hover:bg-background/50 hover:text-foreground/80',
buttonClassName,
)}
>
{option.label}
</button>
);
})}
</div>
);
}