diff --git a/src/components/ui/button.tsx b/src/components/ui/button.tsx index 2adaf00..795c488 100644 --- a/src/components/ui/button.tsx +++ b/src/components/ui/button.tsx @@ -1,36 +1,34 @@ -import * as React from "react"; -import { Slot } from "@radix-ui/react-slot"; -import { cva, type VariantProps } from "class-variance-authority"; +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"; +import { cn } from '@/lib/utils'; const buttonVariants = cva( - "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive", + "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-lg border border-transparent text-sm font-semibold transition-[transform,colors,shadow] shadow-[0_10px_30px_-18px_rgba(0,0,0,0.45)] disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:ring-2 focus-visible:ring-primary/40 focus-visible:ring-offset-2 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive", { variants: { variant: { default: - "bg-primary text-primary-foreground shadow-xs hover:bg-primary/90", + 'border-primary/20 bg-gradient-to-r from-primary to-secondary text-primary-foreground shadow-lg shadow-primary/30 hover:from-primary/90 hover:to-secondary/90', destructive: - "bg-destructive text-white shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60", + 'bg-destructive text-white shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60', outline: - "border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50", - secondary: - "bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80", - ghost: - "hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50", - link: "text-primary underline-offset-4 hover:underline", + 'border border-primary/25 bg-background/80 shadow-sm hover:bg-primary/10 hover:text-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50', + secondary: 'bg-secondary/90 text-secondary-foreground shadow-md hover:bg-secondary', + ghost: 'text-foreground/80 hover:bg-primary/10 hover:text-foreground dark:hover:bg-accent/50', + link: 'text-primary underline-offset-4 hover:underline', }, size: { - default: "h-9 px-4 py-2 has-[>svg]:px-3", - sm: "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5", - lg: "h-10 rounded-md px-6 has-[>svg]:px-4", - icon: "size-9", + default: 'h-9 px-4 py-2 has-[>svg]:px-3.5', + sm: 'h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5', + lg: 'h-11 rounded-md px-5 has-[>svg]:px-4', + icon: 'size-9', }, }, defaultVariants: { - variant: "default", - size: "default", + variant: 'default', + size: 'default', }, }, ); @@ -41,18 +39,14 @@ function Button({ size, asChild = false, ...props -}: React.ComponentProps<"button"> & +}: React.ComponentProps<'button'> & VariantProps & { asChild?: boolean; }) { - const Comp = asChild ? Slot : "button"; + const Comp = asChild ? Slot : 'button'; return ( - + ); } diff --git a/src/components/ui/chart.tsx b/src/components/ui/chart.tsx index 31fef82..4559a0c 100644 --- a/src/components/ui/chart.tsx +++ b/src/components/ui/chart.tsx @@ -1,23 +1,20 @@ /* eslint-disable @typescript-eslint/no-unsafe-assignment */ -"use client"; +'use client'; -import * as React from "react"; -import * as RechartsPrimitive from "recharts"; +import * as React from 'react'; +import * as RechartsPrimitive from 'recharts'; -import { cn } from "@/lib/utils"; +import { cn } from '@/lib/utils'; // Format: { THEME_NAME: CSS_SELECTOR } -const THEMES = { light: "", dark: ".dark" } as const; +const THEMES = { light: '', dark: '.dark' } as const; export type ChartConfig = Record< string, { label?: React.ReactNode; icon?: React.ComponentType; - } & ( - | { color?: string; theme?: never } - | { color?: never; theme: Record } - ) + } & ({ color?: string; theme?: never } | { color?: never; theme: Record }) >; interface ChartContextProps { @@ -30,7 +27,7 @@ function useChart() { const context = React.useContext(ChartContext); if (!context) { - throw new Error("useChart must be used within a "); + throw new Error('useChart must be used within a '); } return context; @@ -42,14 +39,12 @@ function ChartContainer({ children, config, ...props -}: React.ComponentProps<"div"> & { +}: React.ComponentProps<'div'> & { config: ChartConfig; - children: React.ComponentProps< - typeof RechartsPrimitive.ResponsiveContainer - >["children"]; + children: React.ComponentProps['children']; }) { const uniqueId = React.useId(); - const chartId = `chart-${id ?? uniqueId.replace(/:/g, "")}`; + const chartId = `chart-${id ?? uniqueId.replace(/:/g, '')}`; return ( @@ -63,18 +58,14 @@ function ChartContainer({ {...props} > - - {children} - + {children} ); } const ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => { - const colorConfig = Object.entries(config).filter( - ([, config]) => config.theme ?? config.color, - ); + const colorConfig = Object.entries(config).filter(([, config]) => config.theme ?? config.color); if (!colorConfig.length) { return null; @@ -89,16 +80,14 @@ const ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => { ${prefix} [data-chart=${id}] { ${colorConfig .map(([key, itemConfig]) => { - const color = - itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ?? - itemConfig.color; + const color = itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ?? itemConfig.color; return color ? ` --color-${key}: ${color};` : null; }) - .join("\n")} + .join('\n')} } `, ) - .join("\n"), + .join('\n'), }} /> ); @@ -110,7 +99,7 @@ function ChartTooltipContent({ active, payload, className, - indicator = "dot", + indicator = 'dot', hideLabel = false, hideIndicator = false, label, @@ -121,10 +110,10 @@ function ChartTooltipContent({ nameKey, labelKey, }: React.ComponentProps & - React.ComponentProps<"div"> & { + React.ComponentProps<'div'> & { hideLabel?: boolean; hideIndicator?: boolean; - indicator?: "line" | "dot" | "dashed"; + indicator?: 'line' | 'dot' | 'dashed'; nameKey?: string; labelKey?: string; }) { @@ -136,53 +125,41 @@ function ChartTooltipContent({ } const item = payload[0]; - const key = labelKey ?? String(item.dataKey ?? item.name ?? "value"); + const key = labelKey ?? String(item.dataKey ?? item.name ?? 'value'); const itemConfig = getPayloadConfigFromPayload(config, item, key); const value = - !labelKey && typeof label === "string" - ? (label in config && config[label].label ? config[label].label : undefined) ?? label + !labelKey && typeof label === 'string' + ? ((label in config && config[label].label ? config[label].label : undefined) ?? label) : itemConfig?.label; if (labelFormatter) { - return ( -
- {labelFormatter(value, payload)} -
- ); + return
{labelFormatter(value, payload)}
; } if (!value) { return null; } - return
{value}
; - }, [ - label, - labelFormatter, - payload, - hideLabel, - labelClassName, - config, - labelKey, - ]); + return
{value}
; + }, [label, labelFormatter, payload, hideLabel, labelClassName, config, labelKey]); if (!active || !payload?.length) { return null; } - const nestLabel = payload.length === 1 && indicator !== "dot"; + const nestLabel = payload.length === 1 && indicator !== 'dot'; return (
{!nestLabel ? tooltipLabel : null}
{payload.map((item, index) => { - const key = nameKey ?? String(item.name ?? item.dataKey ?? "value"); + const key = nameKey ?? String(item.name ?? item.dataKey ?? 'value'); const itemConfig = getPayloadConfigFromPayload(config, item, key); const indicatorColor: string | undefined = // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access @@ -192,8 +169,8 @@ function ChartTooltipContent({
svg]:text-muted-foreground flex w-full flex-wrap items-stretch gap-2 [&>svg]:h-2.5 [&>svg]:w-2.5", - indicator === "dot" && "items-center", + '[&>svg]:text-muted-foreground flex w-full flex-wrap items-stretch gap-2 [&>svg]:h-2.5 [&>svg]:w-2.5', + indicator === 'dot' && 'items-center', )} > {formatter && item.value !== undefined && item.name ? ( @@ -206,20 +183,16 @@ function ChartTooltipContent({ ) : ( !hideIndicator && (
@@ -227,15 +200,13 @@ function ChartTooltipContent({ )}
{nestLabel ? tooltipLabel : null} - - {itemConfig?.label ?? item.name} - + {itemConfig?.label ?? item.name}
{item.value && ( @@ -259,10 +230,10 @@ function ChartLegendContent({ className, hideIcon = false, payload, - verticalAlign = "bottom", + verticalAlign = 'bottom', nameKey, -}: React.ComponentProps<"div"> & - Pick & { +}: React.ComponentProps<'div'> & + Pick & { hideIcon?: boolean; nameKey?: string; }) { @@ -275,21 +246,21 @@ function ChartLegendContent({ return (
{payload.map((item) => { // eslint-disable-next-line @typescript-eslint/restrict-template-expressions - const key = `${nameKey ?? item.dataKey ?? "value"}`; + const key = `${nameKey ?? item.dataKey ?? 'value'}`; const itemConfig = getPayloadConfigFromPayload(config, item, key); return (
svg]:text-muted-foreground flex items-center gap-1.5 [&>svg]:h-3 [&>svg]:w-3", + '[&>svg]:text-muted-foreground flex items-center gap-1.5 [&>svg]:h-3 [&>svg]:w-3', )} > {itemConfig?.icon && !hideIcon ? ( @@ -311,37 +282,26 @@ function ChartLegendContent({ } // Helper to extract item config from a payload. -function getPayloadConfigFromPayload( - config: ChartConfig, - payload: unknown, - key: string, -) { - if (typeof payload !== "object" || payload === null) { +function getPayloadConfigFromPayload(config: ChartConfig, payload: unknown, key: string) { + if (typeof payload !== 'object' || payload === null) { return undefined; } const payloadPayload = - "payload" in payload && - typeof payload.payload === "object" && - payload.payload !== null + 'payload' in payload && typeof payload.payload === 'object' && payload.payload !== null ? payload.payload : undefined; let configLabelKey: string = key; - if ( - key in payload && - typeof payload[key as keyof typeof payload] === "string" - ) { + if (key in payload && typeof payload[key as keyof typeof payload] === 'string') { configLabelKey = payload[key as keyof typeof payload] as string; } else if ( payloadPayload && key in payloadPayload && - typeof payloadPayload[key as keyof typeof payloadPayload] === "string" + typeof payloadPayload[key as keyof typeof payloadPayload] === 'string' ) { - configLabelKey = payloadPayload[ - key as keyof typeof payloadPayload - ] as string; + configLabelKey = payloadPayload[key as keyof typeof payloadPayload] as string; } return configLabelKey in config ? config[configLabelKey] : config[key]; diff --git a/src/components/ui/sheet.tsx b/src/components/ui/sheet.tsx index 9603edd..4b15ece 100644 --- a/src/components/ui/sheet.tsx +++ b/src/components/ui/sheet.tsx @@ -27,7 +27,7 @@ function SheetOverlay({ className, ...props }: React.ComponentPropsli]:mt-2; + } + code { + @apply bg-muted relative rounded px-[0.3rem] py-[0.2rem] font-mono text-sm font-semibold + } }