set up eslint and prettier

This commit is contained in:
2026-02-12 20:54:14 +01:00
parent 759e336956
commit 316055652f
60 changed files with 12758 additions and 2724 deletions

View File

@@ -0,0 +1,3 @@
import reactConfig from "@zendegi/eslint-config/react";
export default reactConfig;

View File

@@ -5,7 +5,8 @@
"scripts": {
"build": "vite build",
"serve": "vite preview",
"dev": "vite dev"
"dev": "vite dev",
"lint": "eslint ."
},
"dependencies": {
"@base-ui/react": "^1.0.0",
@@ -42,6 +43,8 @@
"@types/react-dom": "19.2.3",
"@vitejs/plugin-react": "^5.0.4",
"@zendegi/config": "workspace:*",
"@zendegi/eslint-config": "workspace:*",
"eslint": "^9.17.0",
"jsdom": "^26.0.0",
"typescript": "catalog:",
"vite": "^7.0.2",

View File

@@ -3,14 +3,17 @@ import { useNavigate } from "@tanstack/react-router";
import { toast } from "sonner";
import z from "zod";
import { authClient } from "@/lib/auth-client";
import Loader from "./loader";
import { Button } from "./ui/button";
import { Input } from "./ui/input";
import { Label } from "./ui/label";
import { authClient } from "@/lib/auth-client";
export default function SignInForm({ onSwitchToSignUp }: { onSwitchToSignUp: () => void }) {
export default function SignInForm({
onSwitchToSignUp,
}: {
onSwitchToSignUp: () => void;
}) {
const navigate = useNavigate({
from: "/",
});
@@ -37,7 +40,7 @@ export default function SignInForm({ onSwitchToSignUp }: { onSwitchToSignUp: ()
onError: (error) => {
toast.error(error.error.message || error.error.statusText);
},
},
}
);
},
validators: {

View File

@@ -3,14 +3,17 @@ import { useNavigate } from "@tanstack/react-router";
import { toast } from "sonner";
import z from "zod";
import { authClient } from "@/lib/auth-client";
import Loader from "./loader";
import { Button } from "./ui/button";
import { Input } from "./ui/input";
import { Label } from "./ui/label";
import { authClient } from "@/lib/auth-client";
export default function SignUpForm({ onSwitchToSignIn }: { onSwitchToSignIn: () => void }) {
export default function SignUpForm({
onSwitchToSignIn,
}: {
onSwitchToSignIn: () => void;
}) {
const navigate = useNavigate({
from: "/",
});
@@ -39,7 +42,7 @@ export default function SignUpForm({ onSwitchToSignIn }: { onSwitchToSignIn: ()
onError: (error) => {
toast.error(error.error.message || error.error.statusText);
},
},
}
);
},
validators: {

View File

@@ -1,7 +1,6 @@
import type { VariantProps } from "class-variance-authority";
import { Button as ButtonPrimitive } from "@base-ui/react/button";
import { cva } from "class-variance-authority";
import type { VariantProps } from "class-variance-authority";
import { cn } from "@/lib/utils";
@@ -37,7 +36,7 @@ const buttonVariants = cva(
variant: "default",
size: "default",
},
},
}
);
function Button({

View File

@@ -1,4 +1,4 @@
import * as React from "react";
import type * as React from "react";
import { cn } from "@/lib/utils";
@@ -13,7 +13,7 @@ function Card({
data-size={size}
className={cn(
"ring-foreground/10 bg-card text-card-foreground gap-4 overflow-hidden rounded-none py-4 text-xs/relaxed ring-1 has-data-[slot=card-footer]:pb-0 has-[>img:first-child]:pt-0 data-[size=sm]:gap-2 data-[size=sm]:py-3 data-[size=sm]:has-data-[slot=card-footer]:pb-0 *:[img:first-child]:rounded-none *:[img:last-child]:rounded-none group/card flex flex-col",
className,
className
)}
{...props}
/>
@@ -26,7 +26,7 @@ function CardHeader({ className, ...props }: React.ComponentProps<"div">) {
data-slot="card-header"
className={cn(
"gap-1 rounded-none px-4 group-data-[size=sm]/card:px-3 [.border-b]:pb-4 group-data-[size=sm]/card:[.border-b]:pb-3 group/card-header @container/card-header grid auto-rows-min items-start has-data-[slot=card-action]:grid-cols-[1fr_auto] has-data-[slot=card-description]:grid-rows-[auto_auto]",
className,
className
)}
{...props}
/>
@@ -37,7 +37,10 @@ function CardTitle({ className, ...props }: React.ComponentProps<"div">) {
return (
<div
data-slot="card-title"
className={cn("text-sm font-medium group-data-[size=sm]/card:text-sm", className)}
className={cn(
"text-sm font-medium group-data-[size=sm]/card:text-sm",
className
)}
{...props}
/>
);
@@ -57,7 +60,10 @@ function CardAction({ className, ...props }: React.ComponentProps<"div">) {
return (
<div
data-slot="card-action"
className={cn("col-start-2 row-span-2 row-start-1 self-start justify-self-end", className)}
className={cn(
"col-start-2 row-span-2 row-start-1 self-start justify-self-end",
className
)}
{...props}
/>
);
@@ -79,11 +85,19 @@ function CardFooter({ className, ...props }: React.ComponentProps<"div">) {
data-slot="card-footer"
className={cn(
"rounded-none border-t p-4 group-data-[size=sm]/card:p-3 flex items-center",
className,
className
)}
{...props}
/>
);
}
export { Card, CardHeader, CardFooter, CardTitle, CardAction, CardDescription, CardContent };
export {
Card,
CardHeader,
CardFooter,
CardTitle,
CardAction,
CardDescription,
CardContent,
};

View File

@@ -9,7 +9,7 @@ function Checkbox({ className, ...props }: CheckboxPrimitive.Root.Props) {
data-slot="checkbox"
className={cn(
"border-input dark:bg-input/30 data-checked:bg-primary data-checked:text-primary-foreground dark:data-checked:bg-primary data-checked:border-primary aria-invalid:aria-checked:border-primary aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 flex size-4 items-center justify-center rounded-none border transition-colors group-has-disabled/field:opacity-50 focus-visible:ring-1 aria-invalid:ring-1 peer relative shrink-0 outline-none after:absolute after:-inset-x-3 after:-inset-y-2 disabled:cursor-not-allowed disabled:opacity-50",
className,
className
)}
{...props}
>

View File

@@ -1,6 +1,6 @@
import { Menu as MenuPrimitive } from "@base-ui/react/menu";
import { CheckIcon, ChevronRightIcon } from "lucide-react";
import * as React from "react";
import type * as React from "react";
import { cn } from "@/lib/utils";
@@ -24,7 +24,10 @@ function DropdownMenuContent({
className,
...props
}: MenuPrimitive.Popup.Props &
Pick<MenuPrimitive.Positioner.Props, "align" | "alignOffset" | "side" | "sideOffset">) {
Pick<
MenuPrimitive.Positioner.Props,
"align" | "alignOffset" | "side" | "sideOffset"
>) {
return (
<MenuPrimitive.Portal>
<MenuPrimitive.Positioner
@@ -38,7 +41,7 @@ function DropdownMenuContent({
data-slot="dropdown-menu-content"
className={cn(
"data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 ring-foreground/10 bg-popover text-popover-foreground min-w-32 rounded-none shadow-md ring-1 duration-100 z-50 max-h-(--available-height) w-(--anchor-width) origin-(--transform-origin) overflow-x-hidden overflow-y-auto outline-none data-closed:overflow-hidden",
className,
className
)}
{...props}
/>
@@ -62,7 +65,10 @@ function DropdownMenuLabel({
<MenuPrimitive.GroupLabel
data-slot="dropdown-menu-label"
data-inset={inset}
className={cn("text-muted-foreground px-2 py-2 text-xs data-[inset]:pl-8", className)}
className={cn(
"text-muted-foreground px-2 py-2 text-xs data-[inset]:pl-8",
className
)}
{...props}
/>
);
@@ -84,7 +90,7 @@ function DropdownMenuItem({
data-variant={variant}
className={cn(
"focus:bg-accent focus:text-accent-foreground data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 dark:data-[variant=destructive]:focus:bg-destructive/20 data-[variant=destructive]:focus:text-destructive data-[variant=destructive]:*:[svg]:text-destructive not-data-[variant=destructive]:focus:**:text-accent-foreground gap-2 rounded-none px-2 py-2 text-xs [&_svg:not([class*='size-'])]:size-4 group/dropdown-menu-item relative flex cursor-default items-center outline-hidden select-none data-disabled:pointer-events-none data-disabled:opacity-50 data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0",
className,
className
)}
{...props}
/>
@@ -109,7 +115,7 @@ function DropdownMenuSubTrigger({
data-inset={inset}
className={cn(
"focus:bg-accent focus:text-accent-foreground data-open:bg-accent data-open:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground gap-2 rounded-none px-2 py-2 text-xs [&_svg:not([class*='size-'])]:size-4 flex cursor-default items-center outline-hidden select-none data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0",
className,
className
)}
{...props}
>
@@ -132,7 +138,7 @@ function DropdownMenuSubContent({
data-slot="dropdown-menu-sub-content"
className={cn(
"data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 ring-foreground/10 bg-popover text-popover-foreground min-w-[96px] rounded-none shadow-lg ring-1 duration-100 w-auto",
className,
className
)}
align={align}
alignOffset={alignOffset}
@@ -154,7 +160,7 @@ function DropdownMenuCheckboxItem({
data-slot="dropdown-menu-checkbox-item"
className={cn(
"focus:bg-accent focus:text-accent-foreground focus:**:text-accent-foreground gap-2 rounded-none py-2 pr-8 pl-2 text-xs [&_svg:not([class*='size-'])]:size-4 relative flex cursor-default items-center outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0",
className,
className
)}
checked={checked}
{...props}
@@ -173,16 +179,25 @@ function DropdownMenuCheckboxItem({
}
function DropdownMenuRadioGroup({ ...props }: MenuPrimitive.RadioGroup.Props) {
return <MenuPrimitive.RadioGroup data-slot="dropdown-menu-radio-group" {...props} />;
return (
<MenuPrimitive.RadioGroup
data-slot="dropdown-menu-radio-group"
{...props}
/>
);
}
function DropdownMenuRadioItem({ className, children, ...props }: MenuPrimitive.RadioItem.Props) {
function DropdownMenuRadioItem({
className,
children,
...props
}: MenuPrimitive.RadioItem.Props) {
return (
<MenuPrimitive.RadioItem
data-slot="dropdown-menu-radio-item"
className={cn(
"focus:bg-accent focus:text-accent-foreground focus:**:text-accent-foreground gap-2 rounded-none py-2 pr-8 pl-2 text-xs [&_svg:not([class*='size-'])]:size-4 relative flex cursor-default items-center outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0",
className,
className
)}
{...props}
>
@@ -199,7 +214,10 @@ function DropdownMenuRadioItem({ className, children, ...props }: MenuPrimitive.
);
}
function DropdownMenuSeparator({ className, ...props }: MenuPrimitive.Separator.Props) {
function DropdownMenuSeparator({
className,
...props
}: MenuPrimitive.Separator.Props) {
return (
<MenuPrimitive.Separator
data-slot="dropdown-menu-separator"
@@ -209,13 +227,16 @@ function DropdownMenuSeparator({ className, ...props }: MenuPrimitive.Separator.
);
}
function DropdownMenuShortcut({ className, ...props }: React.ComponentProps<"span">) {
function DropdownMenuShortcut({
className,
...props
}: React.ComponentProps<"span">) {
return (
<span
data-slot="dropdown-menu-shortcut"
className={cn(
"text-muted-foreground group-focus/dropdown-menu-item:text-accent-foreground ml-auto text-xs tracking-widest",
className,
className
)}
{...props}
/>

View File

@@ -1,5 +1,5 @@
import { Input as InputPrimitive } from "@base-ui/react/input";
import * as React from "react";
import type * as React from "react";
import { cn } from "@/lib/utils";
@@ -10,7 +10,7 @@ function Input({ className, type, ...props }: React.ComponentProps<"input">) {
data-slot="input"
className={cn(
"dark:bg-input/30 border-input focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 disabled:bg-input/50 dark:disabled:bg-input/80 h-8 rounded-none border bg-transparent px-2.5 py-1 text-xs transition-colors file:h-6 file:text-xs file:font-medium focus-visible:ring-1 aria-invalid:ring-1 md:text-xs file:text-foreground placeholder:text-muted-foreground w-full min-w-0 outline-none file:inline-flex file:border-0 file:bg-transparent disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50",
className,
className
)}
{...props}
/>

View File

@@ -1,16 +1,17 @@
"use client";
import * as React from "react";
import type * as React from "react";
import { cn } from "@/lib/utils";
function Label({ className, ...props }: React.ComponentProps<"label">) {
return (
// eslint-disable-next-line jsx-a11y/label-has-associated-control -- htmlFor is passed via ...props
<label
data-slot="label"
className={cn(
"gap-2 text-xs leading-none group-data-[disabled=true]:opacity-50 peer-disabled:opacity-50 flex items-center select-none group-data-[disabled=true]:pointer-events-none peer-disabled:cursor-not-allowed",
className,
className
)}
{...props}
/>

View File

@@ -1,6 +1,9 @@
import { cn } from "@/lib/utils";
function Skeleton({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) {
function Skeleton({
className,
...props
}: React.HTMLAttributes<HTMLDivElement>) {
return (
<div
data-slot="skeleton"

View File

@@ -1,5 +1,3 @@
import type { ToasterProps } from "sonner";
import {
CircleCheckIcon,
InfoIcon,
@@ -9,6 +7,7 @@ import {
} from "lucide-react";
import { useTheme } from "next-themes";
import { Toaster as Sonner } from "sonner";
import type { ToasterProps } from "sonner";
const Toaster = ({ ...props }: ToasterProps) => {
const { theme = "system" } = useTheme();

View File

@@ -1,5 +1,7 @@
import { Link, useNavigate } from "@tanstack/react-router";
import { Button } from "./ui/button";
import { Skeleton } from "./ui/skeleton";
import {
DropdownMenu,
DropdownMenuContent,
@@ -11,9 +13,6 @@ import {
} from "@/components/ui/dropdown-menu";
import { authClient } from "@/lib/auth-client";
import { Button } from "./ui/button";
import { Skeleton } from "./ui/skeleton";
export default function UserMenu() {
const navigate = useNavigate();
const { data: session, isPending } = authClient.useSession();

View File

@@ -1,6 +1,7 @@
import { clsx, type ClassValue } from "clsx";
import { clsx } from "clsx";
import { twMerge } from "tailwind-merge";
import type { ClassValue } from "clsx";
export function cn(...inputs: ClassValue[]) {
export function cn(...inputs: Array<ClassValue>) {
return twMerge(clsx(inputs));
}

View File

@@ -1,11 +1,13 @@
import { createMiddleware } from "@tanstack/react-start";
import { auth } from "@zendegi/auth";
export const authMiddleware = createMiddleware().server(async ({ next, request }) => {
const session = await auth.api.getSession({
headers: request.headers,
});
return next({
context: { session },
});
});
export const authMiddleware = createMiddleware().server(
async ({ next, request }) => {
const session = await auth.api.getSession({
headers: request.headers,
});
return next({
context: { session },
});
}
);

View File

@@ -1,10 +1,14 @@
import { HeadContent, Outlet, Scripts, createRootRouteWithContext } from "@tanstack/react-router";
import {
HeadContent,
Outlet,
Scripts,
createRootRouteWithContext,
} from "@tanstack/react-router";
import { TanStackRouterDevtools } from "@tanstack/react-router-devtools";
import { Toaster } from "@/components/ui/sonner";
import Header from "../components/header";
import appCss from "../index.css?url";
import { Toaster } from "@/components/ui/sonner";
export interface RouterAppContext {}