diff --git a/src/app/api/dashboard/route.ts b/src/app/api/dashboard/route.ts index 0ec73cc..73cf016 100644 --- a/src/app/api/dashboard/route.ts +++ b/src/app/api/dashboard/route.ts @@ -1,9 +1,9 @@ -import { NextResponse } from 'next/server'; -import http from 'node:http'; +import { NextResponse } from "next/server"; +import http from "node:http"; -const JAEGER = 'http://jaeger:16686'; -const PROMETHEUS = 'http://prometheus:9090'; -const DOCKER_SOCK = '/var/run/docker.sock'; +const JAEGER = "http://jaeger:16686"; +const PROMETHEUS = "http://prometheus:9090"; +const DOCKER_SOCK = "/var/run/docker.sock"; interface Container { Names: string[]; @@ -28,17 +28,19 @@ interface Service { function dockerFetch(path: string): Promise { return new Promise((resolve, reject) => { - http.get({ socketPath: DOCKER_SOCK, path }, (res) => { - let data = ''; - res.on('data', (c: string) => (data += c)); - res.on('end', () => { - try { - resolve(JSON.parse(data)); - } catch { - resolve(null); - } - }); - }).on('error', reject); + http + .get({ socketPath: DOCKER_SOCK, path }, (res) => { + let data = ""; + res.on("data", (c: string) => (data += c)); + res.on("end", () => { + try { + resolve(JSON.parse(data)); + } catch { + resolve(null); + } + }); + }) + .on("error", reject); }); } @@ -52,27 +54,29 @@ async function fetchJSON(url: string): Promise { } function parseServices(containers: Container[]): Service[] { - const project = containers.find((c) => c.Labels['com.docker.compose.project']) - ?.Labels['com.docker.compose.project']; + const project = containers.find((c) => c.Labels["com.docker.compose.project"]) + ?.Labels["com.docker.compose.project"]; return containers .filter((c) => { - if (!c.NetworkSettings?.Networks?.['app-shared-net']) return false; - if (project && c.Labels['com.docker.compose.project'] !== project) return false; + if (!c.NetworkSettings?.Networks?.["app-shared-net"]) return false; + if (project && c.Labels["com.docker.compose.project"] !== project) + return false; return true; }) .map((c) => ({ - name: c.Names[0].replace(/^\//, ''), + name: c.Names[0].replace(/^\//, ""), state: c.State, hasWeb: Object.keys(c.Labels).some( - (k) => k.startsWith('traefik.http.routers.') && k.endsWith('.rule'), + (k) => k.startsWith("traefik.http.routers.") && k.endsWith(".rule"), ), })); } async function fetchTraces(): Promise { const svcRes = await fetchJSON(`${JAEGER}/api/services`); - if (!svcRes || !Array.isArray((svcRes as { data?: string[] }).data)) return []; + if (!svcRes || !Array.isArray((svcRes as { data?: string[] }).data)) + return []; const now = Date.now() * 1000; const start = now - 5 * 60 * 1_000_000; @@ -84,12 +88,24 @@ async function fetchTraces(): Promise { ); if (!d || !Array.isArray((d as { data?: unknown[] }).data)) continue; - for (const t of (d as { data: { duration: number; spans: { operationName: string; processID: string; tags: { key: string; value: unknown }[] }[]; processes: Record }[] }).data) { + for (const t of ( + d as { + data: { + duration: number; + spans: { + operationName: string; + processID: string; + tags: { key: string; value: unknown }[]; + }[]; + processes: Record; + }[]; + } + ).data) { if (!t.spans?.length) continue; const span = t.spans[0]; - const svc = t.processes[span.processID]?.serviceName || 'unknown'; + const svc = t.processes[span.processID]?.serviceName || "unknown"; const hasError = t.spans.some((s) => - s.tags?.some((tag) => tag.key === 'error' && tag.value === true), + s.tags?.some((tag) => tag.key === "error" && tag.value === true), ); all.push({ service: svc, @@ -108,16 +124,21 @@ async function promRange(query: string, steps = 20): Promise { const now = Math.floor(Date.now() / 1000); const u = `${PROMETHEUS}/api/v1/query_range?query=${encodeURIComponent(query)}&start=${now - 300}&end=${now}&step=${(300 / steps).toFixed(0)}`; const d = await fetchJSON(u); - const result = (d as { data?: { result?: { values?: unknown[][] }[] } })?.data?.result; + const result = (d as { data?: { result?: { values?: unknown[][] }[] } })?.data + ?.result; if (!result?.[0]?.values) return []; - return result[0].values.map((v) => { const f = parseFloat(v[1] as string); return isNaN(f) ? 0 : f; }); + return result[0].values.map((v) => { + const f = parseFloat(v[1] as string); + return isNaN(f) ? 0 : f; + }); } async function promQuery(query: string): Promise { const d = await fetchJSON( `${PROMETHEUS}/api/v1/query?query=${encodeURIComponent(query)}`, ); - const result = (d as { data?: { result?: { value?: unknown[] }[] } })?.data?.result; + const result = (d as { data?: { result?: { value?: unknown[] }[] } })?.data + ?.result; if (!result?.length) return null; const val = result[0].value?.[1]; return val ? parseFloat(val as string) : null; @@ -145,39 +166,62 @@ interface DashboardData { export async function GET() { const [containersRaw] = await Promise.all([ - dockerFetch('/containers/json?all=true') as Promise, + dockerFetch("/containers/json?all=true") as Promise, ]); const containers = Array.isArray(containersRaw) ? containersRaw : []; const services = parseServices(containers); - const [traces, cpu, ram, disk, load1, load5, load15, netIn, netOut, rps, latency, errors] = - await Promise.all([ - fetchTraces(), - promQuery(`100 - (avg by(instance)(rate(node_cpu_seconds_total{mode="idle"}[1m])) * 100)`), - promQuery(`(1 - node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes) * 100`), - promQuery(`(1 - node_filesystem_avail_bytes{mountpoint="/",fstype!="tmpfs"} / node_filesystem_size_bytes{mountpoint="/",fstype!="tmpfs"}) * 100`), - promQuery('node_load1'), - promQuery('node_load5'), - promQuery('node_load15'), - promQuery(`rate(node_network_receive_bytes_total{device!="lo"}[1m])`), - promQuery(`rate(node_network_transmit_bytes_total{device!="lo"}[1m])`), - promRange('sum(rate(traefik_service_requests_total[1m]))'), - promRange('avg(traefik_service_request_duration_seconds_sum / traefik_service_request_duration_seconds_count) * 1000'), - promRange('sum(rate(traefik_service_requests_total{code=~"5.."}[1m]))'), - ]); + const [ + traces, + cpu, + ram, + disk, + load1, + load5, + load15, + netIn, + netOut, + rps, + latency, + errors, + ] = await Promise.all([ + fetchTraces(), + promQuery( + `100 - (avg by(instance)(rate(node_cpu_seconds_total{mode="idle"}[1m])) * 100)`, + ), + promQuery( + `(1 - node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes) * 100`, + ), + promQuery( + `(1 - node_filesystem_avail_bytes{mountpoint="/",fstype!="tmpfs"} / node_filesystem_size_bytes{mountpoint="/",fstype!="tmpfs"}) * 100`, + ), + promQuery("node_load1"), + promQuery("node_load5"), + promQuery("node_load15"), + promQuery(`rate(node_network_receive_bytes_total{device!="lo"}[1m])`), + promQuery(`rate(node_network_transmit_bytes_total{device!="lo"}[1m])`), + promRange("sum(rate(traefik_service_requests_total[1m]))"), + promRange( + "avg(traefik_service_request_duration_seconds_sum / traefik_service_request_duration_seconds_count) * 1000", + ), + promRange('sum(rate(traefik_service_requests_total{code=~"5.."}[1m]))'), + ]); const links: { url: string; label: string }[] = [ - { url: '/jaeger', label: 'Jaeger UI' }, + { url: "/jaeger", label: "Jaeger UI" }, ]; - if (containers.some((c) => c.Names?.some((n) => n.includes('prometheus')))) { - links.push({ url: '/api/prometheus/targets', label: 'Prometheus' }); + if (containers.some((c) => c.Names?.some((n) => n.includes("prometheus")))) { + links.push({ url: "/api/prometheus/targets", label: "Prometheus" }); } - links.push({ url: 'https://github.com/asepharyana/asepharyana-hub', label: 'GitHub' }); + links.push({ + url: "https://github.com/asepharyana/asepharyana-hub", + label: "GitHub", + }); - const domains = ['asepharyana.my.id', 'asepharyana.web.id']; + const domains = ["asepharyana.my.id", "asepharyana.web.id"]; for (const s of services) { - if (s.hasWeb && s.state === 'running') { + if (s.hasWeb && s.state === "running") { links.push({ url: `https://${s.name}.${domains[0]}`, label: s.name }); } } @@ -188,7 +232,10 @@ export async function GET() { services, traces, node: { cpu, ram, disk, load1, load5, load15, netIn, netOut }, - rps, latency, errors, traceVolume, + rps, + latency, + errors, + traceVolume, links, }; diff --git a/src/app/dashboard/page.tsx b/src/app/dashboard/page.tsx index b55f594..6bf7df3 100644 --- a/src/app/dashboard/page.tsx +++ b/src/app/dashboard/page.tsx @@ -1,6 +1,8 @@ -'use client'; +"use client"; -import { useEffect, useState } from 'react'; +import { useEffect, useState } from "react"; +import { Card, CardHeader, CardTitle, CardContent } from "@/components/ui/card"; +import { Badge } from "@/components/ui/badge"; interface Service { name: string; @@ -46,50 +48,99 @@ function Donut({ running, degraded }: { running: number; degraded: number }) { const total = running + degraded; if (!total) return ; - const cx = 100, cy = 90, R = 60, circ = 2 * Math.PI * R; + const cx = 100, + cy = 90, + R = 60, + circ = 2 * Math.PI * R; const segs = [ - { n: running, c: '#3fb950', l: 'Running' }, - { n: degraded, c: '#d29922', l: 'Degraded' }, + { n: running, c: "#3fb950", l: "Running" }, + { n: degraded, c: "#d29922", l: "Degraded" }, ]; let off = 0; return ( - {segs.map((s) => { if (!s.n) return null; const frac = s.n / total; const ln = frac * circ; const el = ( - + ); off += ln; return el; })} - {total} - total - {segs.filter(s => s.n).map((s, i) => ( - - - {s.l}: {s.n} - - ))} + + {total} + + + total + + {segs + .filter((s) => s.n) + .map((s, i) => ( + + + + {s.l}: {s.n} + + + ))} ); } function Sparkline({ data, color }: { data: number[]; color: string }) { - const w = 300, h = 160, pl = 45, pt = 20, pr = 10, pb = 25; - const vw = w - pl - pr, vh = h - pt - pb; + const w = 300, + h = 160, + pl = 45, + pt = 20, + pr = 10, + pb = 25; + const vw = w - pl - pr, + vh = h - pt - pb; if (!data.length) return ; const maxV = Math.max(...data.map(Math.abs), 1); - const pts = data.map((v, i) => - `${(pl + vw * i / (data.length - 1)).toFixed(1)},${(pt + vh * (1 - v / maxV)).toFixed(1)}` - ).join(' '); + const pts = data + .map( + (v, i) => + `${(pl + (vw * i) / (data.length - 1)).toFixed(1)},${(pt + vh * (1 - v / maxV)).toFixed(1)}`, + ) + .join(" "); const area = `M${pl},${pt + vh} L${pts} L${pl + vw},${pt + vh} Z`; const lv = data[data.length - 1]; @@ -97,43 +148,129 @@ function Sparkline({ data, color }: { data: number[]; color: string }) { return ( - - {[0, 1, 2, 3, 4].map(i => { - const y = pt + vh * i / 4; + {[0, 1, 2, 3, 4].map((i) => { + const y = pt + (vh * i) / 4; return ( - - {(maxV * (1 - i / 4)).toFixed(0)} + + + {(maxV * (1 - i / 4)).toFixed(0)} + ); })} - - {lv.toFixed(1)} - {data.length > 5 && [...Array(5)].map((_, i) => { - const idx = Math.floor((i + 1) * (data.length - 1) / 5); - const x = pl + vw * idx / (data.length - 1); - return {idx + 1}; - })} + + + {lv.toFixed(1)} + + {data.length > 5 && + [...Array(5)].map((_, i) => { + const idx = Math.floor(((i + 1) * (data.length - 1)) / 5); + const x = pl + (vw * idx) / (data.length - 1); + return ( + + {idx + 1} + + ); + })} ); } -function Gauge({ pct, color, label, unit }: { pct: number | null; color: string; label: string; unit: string }) { +function Gauge({ + pct, + color, + label, + unit, +}: { + pct: number | null; + color: string; + label: string; + unit: string; +}) { if (pct === null || pct <= 0) return ; - const w = 220, h = 100, bw = 200, bh = 14; - const bx = (w - bw) / 2, by = 30; + const w = 220, + h = 100, + bw = 200, + bh = 14; + const bx = (w - bw) / 2, + by = 30; const fw = bw * Math.min(pct / 100, 1); return ( - - {fw > 0 && } - {label} - - {pct.toFixed(1)}{unit} + {fw > 0 && ( + + )} + + {label} + + + {pct.toFixed(1)} + {unit} ); @@ -142,29 +279,32 @@ function Gauge({ pct, color, label, unit }: { pct: number | null; color: string; function NoData() { return ( - No data + + No data + ); } -function Pill({ state }: { state: string }) { - const dot: Record = { running: '#3fb950', jaeger: '#58a6ff', exited: '#f85149', restarting: '#d29922' }; - return - - {state} - ; -} - export default function Dashboard() { const [data, setData] = useState(null); - const [time, setTime] = useState(''); + const [time, setTime] = useState(""); useEffect(() => { const fetchData = async () => { try { - const res = await fetch('/api/dashboard'); + const res = await fetch("/api/dashboard"); if (res.ok) setData(await res.json()); - } catch { /* ignore */ } + } catch { + /* ignore */ + } }; fetchData(); const id = setInterval(fetchData, 15000); @@ -172,194 +312,318 @@ export default function Dashboard() { }, []); useEffect(() => { - const tick = () => setTime(new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })); + const tick = () => + setTime( + new Date().toLocaleTimeString([], { + hour: "2-digit", + minute: "2-digit", + }), + ); tick(); const id = setInterval(tick, 10000); return () => clearInterval(id); }, []); - const running = data?.services.filter(s => s.state === 'running').length ?? 0; + const running = + data?.services.filter((s) => s.state === "running").length ?? 0; const degraded = (data?.services.length ?? 0) - running; const hasNode = data?.node.cpu !== null || data?.node.ram !== null; - const hasTraffik = (data?.rps?.length ?? 0) > 0 || (data?.latency?.length ?? 0) > 0; - const hasOTel = false; + const hasTraffik = + (data?.rps?.length ?? 0) > 0 || (data?.latency?.length ?? 0) > 0; const node = data?.node; const gaugeColor = (v: number | null) => { - if (v === null) return '#3fb950'; - if (v > 80) return '#f85149'; - if (v > 60) return '#d29922'; - return '#3fb950'; + if (v === null) return "#3fb950"; + if (v > 80) return "#f85149"; + if (v > 60) return "#d29922"; + return "#3fb950"; }; return ( -
- - -
-
- H -
-

Hub Dashboard

-
-
-
- - - {degraded ? `${degraded} degraded` : 'All Systems Operational'} +
+
+
+ + H - {time} +

Hub Dashboard

+
+
+ + + {degraded ? `${degraded} degraded` : "All Systems Operational"} + + {time}
-
-
+
+
{/* Services */} -
-

Services

{data?.services.length ?? 0}
-
- {data?.services.map(s => ( - - - {s.name} - - )) || No services detected} -
-
+ + + Services + + {data?.services.length ?? 0} + + + + {data?.services.length ? ( +
+ {data.services.map((s) => ( + + + {s.name} + + ))} +
+ ) : ( +

+ No services detected +

+ )} +
+
{/* Overview */} -
-

Overview

-
-
{data?.services.length ?? '-'}
Total
-
{running}
Healthy
-
{data?.traces.length ?? 0}
Traces
-
0
Errors
-
-
+ + + Overview + + +
+
+
+ {data?.services.length ?? "-"} +
+

+ Total +

+
+
+
+ {running} +
+

+ Healthy +

+
+
+
+ {data?.traces.length ?? 0} +
+

+ Traces +

+
+
+
+ 0 +
+

+ Errors +

+
+
+
+
{/* Health */} -
-

Health

-
-
+ + + Health + + + + + {/* Links */} -
-

Links

-
- {data?.links.map(l => ( - {l.label} - ))} -
-
+ + + Links + + +
+ {data?.links.map((l) => ( + + {l.label} + + ))} +
+
+
- {/* Node Resources */} + {/* System Resources */} {hasNode && ( -
-
-

System Resources

- {node?.load1?.toFixed(2)} {node?.load5?.toFixed(2)} {node?.load15?.toFixed(2)} -
-
-
-
-
-
-
+ + + System Resources + + {node?.load1?.toFixed(2)} {node?.load5?.toFixed(2)}{" "} + {node?.load15?.toFixed(2)} + + + +
+ + + +
+
+
)} {/* Request Rate */} {hasTraffik && ( -
-

Request Rate

{data?.rps?.length ? `${data.rps[data.rps.length - 1].toFixed(1)}/s` : '-'}
-
-
+ + + Request Rate + + {data?.rps?.length + ? `${data.rps[data.rps.length - 1].toFixed(1)}/s` + : "-"} + + + + + + )} {/* Latency */} {hasTraffik && ( -
-

Latency

{data?.latency?.length ? `${data.latency[data.latency.length - 1].toFixed(0)}ms` : '-'}
-
-
+ + + Latency + + {data?.latency?.length + ? `${data.latency[data.latency.length - 1].toFixed(0)}ms` + : "-"} + + + + + + )} {/* Error Rate */} {hasTraffik && ( -
-

Error Rate

{data?.errors?.length ? `${data.errors[data.errors.length - 1].toFixed(1)}/s` : '-'}
-
-
+ + + Error Rate + + {data?.errors?.length + ? `${data.errors[data.errors.length - 1].toFixed(1)}/s` + : "-"} + + + + + + )} {/* Trace Volume */} -
-

Trace Volume

{data?.traces.length ?? 0} traces
-
-
+ + + Trace Volume + + {data?.traces.length ?? 0} traces + + + + + + - {/* Traces */} -
-

Recent Traces

{data?.traces.length ?? 0}
- {data?.traces.length ? ( -
    - {data.traces.map((t, i) => ( -
  • -
    -
    {t.service}
    -
    {t.operation}
    -
    -
    - {safeDur(t.duration)} - {t.spans} - {t.hasError && err} -
    -
  • - ))} -
- ) :
No traces — data appears once services send OTel telemetry
} -
+ {/* Recent Traces */} + + + Recent Traces + + {data?.traces.length ?? 0} + + + + {data?.traces.length ? ( +
    + {data.traces.map((t, i) => ( +
  • +
    +
    {t.service}
    +
    + {t.operation} +
    +
    +
    + + {safeDur(t.duration)} + + {t.spans} + {t.hasError && ( + + err + + )} +
    +
  • + ))} +
+ ) : ( +

+ No traces — data appears once services send OTel telemetry +

+ )} +
+
diff --git a/src/app/globals.css b/src/app/globals.css index c56032b..6a25b1b 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -127,4 +127,4 @@ html { @apply font-sans; } -} \ No newline at end of file +} diff --git a/src/components/ui/accordion.tsx b/src/components/ui/accordion.tsx index 597ef3c..6400f00 100644 --- a/src/components/ui/accordion.tsx +++ b/src/components/ui/accordion.tsx @@ -1,7 +1,7 @@ -import { Accordion as AccordionPrimitive } from "@base-ui/react/accordion" +import { Accordion as AccordionPrimitive } from "@base-ui/react/accordion"; -import { cn } from "@/lib/utils" -import { ChevronDownIcon, ChevronUpIcon } from "lucide-react" +import { cn } from "@/lib/utils"; +import { ChevronDownIcon, ChevronUpIcon } from "lucide-react"; function Accordion({ className, ...props }: AccordionPrimitive.Root.Props) { return ( @@ -10,7 +10,7 @@ function Accordion({ className, ...props }: AccordionPrimitive.Root.Props) { className={cn("flex w-full flex-col", className)} {...props} /> - ) + ); } function AccordionItem({ className, ...props }: AccordionPrimitive.Item.Props) { @@ -20,7 +20,7 @@ function AccordionItem({ className, ...props }: AccordionPrimitive.Item.Props) { className={cn("not-last:border-b", className)} {...props} /> - ) + ); } function AccordionTrigger({ @@ -34,16 +34,22 @@ function AccordionTrigger({ data-slot="accordion-trigger" className={cn( "group/accordion-trigger relative flex flex-1 items-start justify-between rounded-lg border border-transparent py-2.5 text-left text-sm font-medium transition-all outline-none hover:underline focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 focus-visible:after:border-ring aria-disabled:pointer-events-none aria-disabled:opacity-50 **:data-[slot=accordion-trigger-icon]:ml-auto **:data-[slot=accordion-trigger-icon]:size-4 **:data-[slot=accordion-trigger-icon]:text-muted-foreground", - className + className, )} {...props} > {children} - - + + - ) + ); } function AccordionContent({ @@ -60,13 +66,13 @@ function AccordionContent({
{children}
- ) + ); } -export { Accordion, AccordionItem, AccordionTrigger, AccordionContent } +export { Accordion, AccordionItem, AccordionTrigger, AccordionContent }; diff --git a/src/components/ui/alert-dialog.tsx b/src/components/ui/alert-dialog.tsx index 0ee2c5f..0bdd7c6 100644 --- a/src/components/ui/alert-dialog.tsx +++ b/src/components/ui/alert-dialog.tsx @@ -1,25 +1,25 @@ -"use client" +"use client"; -import * as React from "react" -import { AlertDialog as AlertDialogPrimitive } from "@base-ui/react/alert-dialog" +import * as React from "react"; +import { AlertDialog as AlertDialogPrimitive } from "@base-ui/react/alert-dialog"; -import { cn } from "@/lib/utils" -import { Button } from "@/components/ui/button" +import { cn } from "@/lib/utils"; +import { Button } from "@/components/ui/button"; function AlertDialog({ ...props }: AlertDialogPrimitive.Root.Props) { - return + return ; } function AlertDialogTrigger({ ...props }: AlertDialogPrimitive.Trigger.Props) { return ( - ) + ); } function AlertDialogPortal({ ...props }: AlertDialogPrimitive.Portal.Props) { return ( - ) + ); } function AlertDialogOverlay({ @@ -31,11 +31,11 @@ function AlertDialogOverlay({ data-slot="alert-dialog-overlay" className={cn( "fixed inset-0 isolate z-50 bg-black/10 duration-100 supports-backdrop-filter:backdrop-blur-xs data-open:animate-in data-open:fade-in-0 data-closed:animate-out data-closed:fade-out-0", - className + className, )} {...props} /> - ) + ); } function AlertDialogContent({ @@ -43,7 +43,7 @@ function AlertDialogContent({ size = "default", ...props }: AlertDialogPrimitive.Popup.Props & { - size?: "default" | "sm" + size?: "default" | "sm"; }) { return ( @@ -53,12 +53,12 @@ function AlertDialogContent({ data-size={size} className={cn( "group/alert-dialog-content fixed top-1/2 left-1/2 z-50 grid w-full -translate-x-1/2 -translate-y-1/2 gap-4 rounded-xl bg-popover p-4 text-popover-foreground ring-1 ring-foreground/10 duration-100 outline-none data-[size=default]:max-w-xs data-[size=sm]:max-w-xs data-[size=default]:sm:max-w-sm data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95", - className + className, )} {...props} /> - ) + ); } function AlertDialogHeader({ @@ -70,11 +70,11 @@ function AlertDialogHeader({ data-slot="alert-dialog-header" className={cn( "grid grid-rows-[auto_1fr] place-items-center gap-1.5 text-center has-data-[slot=alert-dialog-media]:grid-rows-[auto_auto_1fr] has-data-[slot=alert-dialog-media]:gap-x-4 sm:group-data-[size=default]/alert-dialog-content:place-items-start sm:group-data-[size=default]/alert-dialog-content:text-left sm:group-data-[size=default]/alert-dialog-content:has-data-[slot=alert-dialog-media]:grid-rows-[auto_1fr]", - className + className, )} {...props} /> - ) + ); } function AlertDialogFooter({ @@ -86,11 +86,11 @@ function AlertDialogFooter({ data-slot="alert-dialog-footer" className={cn( "-mx-4 -mb-4 flex flex-col-reverse gap-2 rounded-b-xl border-t bg-muted/50 p-4 group-data-[size=sm]/alert-dialog-content:grid group-data-[size=sm]/alert-dialog-content:grid-cols-2 sm:flex-row sm:justify-end", - className + className, )} {...props} /> - ) + ); } function AlertDialogMedia({ @@ -102,11 +102,11 @@ function AlertDialogMedia({ data-slot="alert-dialog-media" className={cn( "mb-2 inline-flex size-10 items-center justify-center rounded-md bg-muted sm:group-data-[size=default]/alert-dialog-content:row-span-2 *:[svg:not([class*='size-'])]:size-6", - className + className, )} {...props} /> - ) + ); } function AlertDialogTitle({ @@ -118,11 +118,11 @@ function AlertDialogTitle({ data-slot="alert-dialog-title" className={cn( "font-heading text-base font-medium sm:group-data-[size=default]/alert-dialog-content:group-has-data-[slot=alert-dialog-media]/alert-dialog-content:col-start-2", - className + className, )} {...props} /> - ) + ); } function AlertDialogDescription({ @@ -134,11 +134,11 @@ function AlertDialogDescription({ data-slot="alert-dialog-description" className={cn( "text-sm text-balance text-muted-foreground md:text-pretty *:[a]:underline *:[a]:underline-offset-3 *:[a]:hover:text-foreground", - className + className, )} {...props} /> - ) + ); } function AlertDialogAction({ @@ -151,7 +151,7 @@ function AlertDialogAction({ className={cn(className)} {...props} /> - ) + ); } function AlertDialogCancel({ @@ -168,7 +168,7 @@ function AlertDialogCancel({ render={ - ) + ); } function CarouselNext({ @@ -207,7 +207,7 @@ function CarouselNext({ size = "icon-sm", ...props }: React.ComponentProps) { - const { orientation, scrollNext, canScrollNext } = useCarousel() + const { orientation, scrollNext, canScrollNext } = useCarousel(); return ( - ) + ); } export { @@ -239,4 +239,4 @@ export { CarouselPrevious, CarouselNext, useCarousel, -} +}; diff --git a/src/components/ui/chart.tsx b/src/components/ui/chart.tsx index 7c2dc84..b59312a 100644 --- a/src/components/ui/chart.tsx +++ b/src/components/ui/chart.tsx @@ -1,42 +1,42 @@ -"use client" +"use client"; -import * as React from "react" -import * as RechartsPrimitive from "recharts" -import type { TooltipValueType } from "recharts" +import * as React from "react"; +import * as RechartsPrimitive from "recharts"; +import type { TooltipValueType } 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; -const INITIAL_DIMENSION = { width: 320, height: 200 } as const -type TooltipNameType = number | string +const INITIAL_DIMENSION = { width: 320, height: 200 } as const; +type TooltipNameType = number | string; export type ChartConfig = Record< string, { - label?: React.ReactNode - icon?: React.ComponentType + label?: React.ReactNode; + icon?: React.ComponentType; } & ( | { color?: string; theme?: never } | { color?: never; theme: Record } ) -> +>; type ChartContextProps = { - config: ChartConfig -} + config: ChartConfig; +}; -const ChartContext = React.createContext(null) +const ChartContext = React.createContext(null); function useChart() { - const context = React.useContext(ChartContext) + 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 + return context; } function ChartContainer({ @@ -47,17 +47,17 @@ function ChartContainer({ initialDimension = INITIAL_DIMENSION, ...props }: React.ComponentProps<"div"> & { - config: ChartConfig + config: ChartConfig; children: React.ComponentProps< typeof RechartsPrimitive.ResponsiveContainer - >["children"] + >["children"]; initialDimension?: { - width: number - height: number - } + width: number; + height: number; + }; }) { - const uniqueId = React.useId() - const chartId = `chart-${id ?? uniqueId.replace(/:/g, "")}` + const uniqueId = React.useId(); + const chartId = `chart-${id ?? uniqueId.replace(/:/g, "")}`; return ( @@ -66,7 +66,7 @@ function ChartContainer({ data-chart={chartId} className={cn( "flex aspect-video justify-center text-xs [&_.recharts-cartesian-axis-tick_text]:fill-muted-foreground [&_.recharts-cartesian-grid_line[stroke='#ccc']]:stroke-border/50 [&_.recharts-curve.recharts-tooltip-cursor]:stroke-border [&_.recharts-dot[stroke='#fff']]:stroke-transparent [&_.recharts-layer]:outline-hidden [&_.recharts-polar-grid_[stroke='#ccc']]:stroke-border [&_.recharts-radial-bar-background-sector]:fill-muted [&_.recharts-rectangle.recharts-tooltip-cursor]:fill-muted [&_.recharts-reference-line_[stroke='#ccc']]:stroke-border [&_.recharts-sector]:outline-hidden [&_.recharts-sector[stroke='#fff']]:stroke-transparent [&_.recharts-surface]:outline-hidden", - className + className, )} {...props} > @@ -78,16 +78,16 @@ function ChartContainer({
- ) + ); } const ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => { const colorConfig = Object.entries(config).filter( - ([, config]) => config.theme ?? config.color - ) + ([, config]) => config.theme ?? config.color, + ); if (!colorConfig.length) { - return null + return null; } return ( @@ -101,20 +101,20 @@ ${colorConfig .map(([key, itemConfig]) => { const color = itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ?? - itemConfig.color - return color ? ` --color-${key}: ${color};` : null + itemConfig.color; + return color ? ` --color-${key}: ${color};` : null; }) .join("\n")} } -` +`, ) .join("\n"), }} /> - ) -} + ); +}; -const ChartTooltip = RechartsPrimitive.Tooltip +const ChartTooltip = RechartsPrimitive.Tooltip; function ChartTooltipContent({ active, @@ -132,11 +132,11 @@ function ChartTooltipContent({ labelKey, }: React.ComponentProps & React.ComponentProps<"div"> & { - hideLabel?: boolean - hideIndicator?: boolean - indicator?: "line" | "dot" | "dashed" - nameKey?: string - labelKey?: string + hideLabel?: boolean; + hideIndicator?: boolean; + indicator?: "line" | "dot" | "dashed"; + nameKey?: string; + labelKey?: string; } & Omit< RechartsPrimitive.DefaultTooltipContentProps< TooltipValueType, @@ -144,34 +144,34 @@ function ChartTooltipContent({ >, "accessibilityLayer" >) { - const { config } = useChart() + const { config } = useChart(); const tooltipLabel = React.useMemo(() => { if (hideLabel || !payload?.length) { - return null + return null; } - const [item] = payload - const key = `${labelKey ?? item?.dataKey ?? item?.name ?? "value"}` - const itemConfig = getPayloadConfigFromPayload(config, item, key) + const [item] = payload; + const key = `${labelKey ?? item?.dataKey ?? item?.name ?? "value"}`; + const itemConfig = getPayloadConfigFromPayload(config, item, key); const value = !labelKey && typeof label === "string" ? (config[label]?.label ?? label) - : itemConfig?.label + : itemConfig?.label; if (labelFormatter) { return (
{labelFormatter(value, payload)}
- ) + ); } if (!value) { - return null + return null; } - return
{value}
+ return
{value}
; }, [ label, labelFormatter, @@ -180,19 +180,19 @@ function ChartTooltipContent({ labelClassName, config, labelKey, - ]) + ]); if (!active || !payload?.length) { - return null + return null; } - const nestLabel = payload.length === 1 && indicator !== "dot" + const nestLabel = payload.length === 1 && indicator !== "dot"; return (
{!nestLabel ? tooltipLabel : null} @@ -200,16 +200,16 @@ function ChartTooltipContent({ {payload .filter((item) => item.type !== "none") .map((item, index) => { - const key = `${nameKey ?? item.name ?? item.dataKey ?? "value"}` - const itemConfig = getPayloadConfigFromPayload(config, item, key) - const indicatorColor = color ?? item.payload?.fill ?? item.color + const key = `${nameKey ?? item.name ?? item.dataKey ?? "value"}`; + const itemConfig = getPayloadConfigFromPayload(config, item, key); + const indicatorColor = color ?? item.payload?.fill ?? item.color; return (
svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground", - indicator === "dot" && "items-center" + indicator === "dot" && "items-center", )} > {formatter && item?.value !== undefined && item.name ? ( @@ -229,7 +229,7 @@ function ChartTooltipContent({ "w-0 border-[1.5px] border-dashed bg-transparent": indicator === "dashed", "my-0.5": nestLabel && indicator === "dashed", - } + }, )} style={ { @@ -243,7 +243,7 @@ function ChartTooltipContent({
@@ -263,14 +263,14 @@ function ChartTooltipContent({ )}
- ) + ); })}
- ) + ); } -const ChartLegend = RechartsPrimitive.Legend +const ChartLegend = RechartsPrimitive.Legend; function ChartLegendContent({ className, @@ -279,13 +279,13 @@ function ChartLegendContent({ verticalAlign = "bottom", nameKey, }: React.ComponentProps<"div"> & { - hideIcon?: boolean - nameKey?: string + hideIcon?: boolean; + nameKey?: string; } & RechartsPrimitive.DefaultLegendContentProps) { - const { config } = useChart() + const { config } = useChart(); if (!payload?.length) { - return null + return null; } return ( @@ -293,20 +293,20 @@ function ChartLegendContent({ className={cn( "flex items-center justify-center gap-4", verticalAlign === "top" ? "pb-3" : "pt-3", - className + className, )} > {payload .filter((item) => item.type !== "none") .map((item, index) => { - const key = `${nameKey ?? item.dataKey ?? "value"}` - const itemConfig = getPayloadConfigFromPayload(config, item, key) + const key = `${nameKey ?? item.dataKey ?? "value"}`; + const itemConfig = getPayloadConfigFromPayload(config, item, key); return (
svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground" + "flex items-center gap-1.5 [&>svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground", )} > {itemConfig?.icon && !hideIcon ? ( @@ -321,19 +321,19 @@ function ChartLegendContent({ )} {itemConfig?.label}
- ) + ); })}
- ) + ); } function getPayloadConfigFromPayload( config: ChartConfig, payload: unknown, - key: string + key: string, ) { if (typeof payload !== "object" || payload === null) { - return undefined + return undefined; } const payloadPayload = @@ -341,15 +341,15 @@ function getPayloadConfigFromPayload( typeof payload.payload === "object" && payload.payload !== null ? payload.payload - : undefined + : undefined; - let configLabelKey: string = key + let configLabelKey: string = key; if ( key in payload && typeof payload[key as keyof typeof payload] === "string" ) { - configLabelKey = payload[key as keyof typeof payload] as string + configLabelKey = payload[key as keyof typeof payload] as string; } else if ( payloadPayload && key in payloadPayload && @@ -357,10 +357,10 @@ function getPayloadConfigFromPayload( ) { configLabelKey = payloadPayload[ key as keyof typeof payloadPayload - ] as string + ] as string; } - return configLabelKey in config ? config[configLabelKey] : config[key] + return configLabelKey in config ? config[configLabelKey] : config[key]; } export { @@ -370,4 +370,4 @@ export { ChartLegend, ChartLegendContent, ChartStyle, -} +}; diff --git a/src/components/ui/checkbox.tsx b/src/components/ui/checkbox.tsx index 4fcd847..780a985 100644 --- a/src/components/ui/checkbox.tsx +++ b/src/components/ui/checkbox.tsx @@ -1,9 +1,9 @@ -"use client" +"use client"; -import { Checkbox as CheckboxPrimitive } from "@base-ui/react/checkbox" +import { Checkbox as CheckboxPrimitive } from "@base-ui/react/checkbox"; -import { cn } from "@/lib/utils" -import { CheckIcon } from "lucide-react" +import { cn } from "@/lib/utils"; +import { CheckIcon } from "lucide-react"; function Checkbox({ className, ...props }: CheckboxPrimitive.Root.Props) { return ( @@ -11,7 +11,7 @@ function Checkbox({ className, ...props }: CheckboxPrimitive.Root.Props) { data-slot="checkbox" className={cn( "peer relative flex size-4 shrink-0 items-center justify-center rounded-[4px] border border-input transition-colors outline-none group-has-disabled/field:opacity-50 after:absolute after:-inset-x-3 after:-inset-y-2 focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 aria-invalid:aria-checked:border-primary dark:bg-input/30 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 data-checked:border-primary data-checked:bg-primary data-checked:text-primary-foreground dark:data-checked:bg-primary", - className + className, )} {...props} > @@ -19,11 +19,10 @@ function Checkbox({ className, ...props }: CheckboxPrimitive.Root.Props) { data-slot="checkbox-indicator" className="grid place-content-center text-current transition-none [&>svg]:size-3.5" > - + - ) + ); } -export { Checkbox } +export { Checkbox }; diff --git a/src/components/ui/collapsible.tsx b/src/components/ui/collapsible.tsx index 488fb33..2e44190 100644 --- a/src/components/ui/collapsible.tsx +++ b/src/components/ui/collapsible.tsx @@ -1,21 +1,21 @@ -"use client" +"use client"; -import { Collapsible as CollapsiblePrimitive } from "@base-ui/react/collapsible" +import { Collapsible as CollapsiblePrimitive } from "@base-ui/react/collapsible"; function Collapsible({ ...props }: CollapsiblePrimitive.Root.Props) { - return + return ; } function CollapsibleTrigger({ ...props }: CollapsiblePrimitive.Trigger.Props) { return ( - ) + ); } function CollapsibleContent({ ...props }: CollapsiblePrimitive.Panel.Props) { return ( - ) + ); } -export { Collapsible, CollapsibleTrigger, CollapsibleContent } +export { Collapsible, CollapsibleTrigger, CollapsibleContent }; diff --git a/src/components/ui/combobox.tsx b/src/components/ui/combobox.tsx index 39e2b93..5408dc6 100644 --- a/src/components/ui/combobox.tsx +++ b/src/components/ui/combobox.tsx @@ -1,22 +1,22 @@ -"use client" +"use client"; -import * as React from "react" -import { Combobox as ComboboxPrimitive } from "@base-ui/react" +import * as React from "react"; +import { Combobox as ComboboxPrimitive } from "@base-ui/react"; -import { cn } from "@/lib/utils" -import { Button } from "@/components/ui/button" +import { cn } from "@/lib/utils"; +import { Button } from "@/components/ui/button"; import { InputGroup, InputGroupAddon, InputGroupButton, InputGroupInput, -} from "@/components/ui/input-group" -import { ChevronDownIcon, XIcon, CheckIcon } from "lucide-react" +} from "@/components/ui/input-group"; +import { ChevronDownIcon, XIcon, CheckIcon } from "lucide-react"; -const Combobox = ComboboxPrimitive.Root +const Combobox = ComboboxPrimitive.Root; function ComboboxValue({ ...props }: ComboboxPrimitive.Value.Props) { - return + return ; } function ComboboxTrigger({ @@ -33,7 +33,7 @@ function ComboboxTrigger({ {children} - ) + ); } function ComboboxClear({ className, ...props }: ComboboxPrimitive.Clear.Props) { @@ -46,7 +46,7 @@ function ComboboxClear({ className, ...props }: ComboboxPrimitive.Clear.Props) { > - ) + ); } function ComboboxInput({ @@ -57,8 +57,8 @@ function ComboboxInput({ showClear = false, ...props }: ComboboxPrimitive.Input.Props & { - showTrigger?: boolean - showClear?: boolean + showTrigger?: boolean; + showClear?: boolean; }) { return ( @@ -81,7 +81,7 @@ function ComboboxInput({ {children} - ) + ); } function ComboboxContent({ @@ -110,12 +110,15 @@ function ComboboxContent({ - ) + ); } function ComboboxList({ className, ...props }: ComboboxPrimitive.List.Props) { @@ -124,11 +127,11 @@ function ComboboxList({ className, ...props }: ComboboxPrimitive.List.Props) { data-slot="combobox-list" className={cn( "no-scrollbar max-h-[min(calc(--spacing(72)---spacing(9)),calc(var(--available-height)---spacing(9)))] scroll-py-1 overflow-y-auto overscroll-contain p-1 data-empty:p-0", - className + className, )} {...props} /> - ) + ); } function ComboboxItem({ @@ -141,7 +144,7 @@ function ComboboxItem({ data-slot="combobox-item" className={cn( "relative flex w-full cursor-default items-center gap-2 rounded-md py-1 pr-8 pl-1.5 text-sm outline-hidden select-none data-highlighted:bg-accent data-highlighted:text-accent-foreground not-data-[variant=destructive]:data-highlighted:**:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", - className + className, )} {...props} > @@ -154,7 +157,7 @@ function ComboboxItem({ - ) + ); } function ComboboxGroup({ className, ...props }: ComboboxPrimitive.Group.Props) { @@ -164,7 +167,7 @@ function ComboboxGroup({ className, ...props }: ComboboxPrimitive.Group.Props) { className={cn(className)} {...props} /> - ) + ); } function ComboboxLabel({ @@ -177,13 +180,13 @@ function ComboboxLabel({ className={cn("px-2 py-1.5 text-xs text-muted-foreground", className)} {...props} /> - ) + ); } function ComboboxCollection({ ...props }: ComboboxPrimitive.Collection.Props) { return ( - ) + ); } function ComboboxEmpty({ className, ...props }: ComboboxPrimitive.Empty.Props) { @@ -192,11 +195,11 @@ function ComboboxEmpty({ className, ...props }: ComboboxPrimitive.Empty.Props) { data-slot="combobox-empty" className={cn( "hidden w-full justify-center py-2 text-center text-sm text-muted-foreground group-data-empty/combobox-content:flex", - className + className, )} {...props} /> - ) + ); } function ComboboxSeparator({ @@ -209,7 +212,7 @@ function ComboboxSeparator({ className={cn("-mx-1 my-1 h-px bg-border", className)} {...props} /> - ) + ); } function ComboboxChips({ @@ -222,11 +225,11 @@ function ComboboxChips({ data-slot="combobox-chips" className={cn( "flex min-h-8 flex-wrap items-center gap-1 rounded-lg border border-input bg-transparent bg-clip-padding px-2.5 py-1 text-sm transition-colors focus-within:border-ring focus-within:ring-3 focus-within:ring-ring/50 has-aria-invalid:border-destructive has-aria-invalid:ring-3 has-aria-invalid:ring-destructive/20 has-data-[slot=combobox-chip]:px-1 dark:bg-input/30 dark:has-aria-invalid:border-destructive/50 dark:has-aria-invalid:ring-destructive/40", - className + className, )} {...props} /> - ) + ); } function ComboboxChip({ @@ -235,14 +238,14 @@ function ComboboxChip({ showRemove = true, ...props }: ComboboxPrimitive.Chip.Props & { - showRemove?: boolean + showRemove?: boolean; }) { return ( @@ -257,7 +260,7 @@ function ComboboxChip({ )} - ) + ); } function ComboboxChipsInput({ @@ -270,11 +273,11 @@ function ComboboxChipsInput({ className={cn("min-w-16 flex-1 outline-none", className)} {...props} /> - ) + ); } function useComboboxAnchor() { - return React.useRef(null) + return React.useRef(null); } export { @@ -294,4 +297,4 @@ export { ComboboxTrigger, ComboboxValue, useComboboxAnchor, -} +}; diff --git a/src/components/ui/command.tsx b/src/components/ui/command.tsx index 37fb2d9..bc3670a 100644 --- a/src/components/ui/command.tsx +++ b/src/components/ui/command.tsx @@ -1,21 +1,18 @@ -"use client" +"use client"; -import * as React from "react" -import { Command as CommandPrimitive } from "cmdk" +import * as React from "react"; +import { Command as CommandPrimitive } from "cmdk"; -import { cn } from "@/lib/utils" +import { cn } from "@/lib/utils"; import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, -} from "@/components/ui/dialog" -import { - InputGroup, - InputGroupAddon, -} from "@/components/ui/input-group" -import { SearchIcon, CheckIcon } from "lucide-react" +} from "@/components/ui/dialog"; +import { InputGroup, InputGroupAddon } from "@/components/ui/input-group"; +import { SearchIcon, CheckIcon } from "lucide-react"; function Command({ className, @@ -26,11 +23,11 @@ function Command({ data-slot="command" className={cn( "flex size-full flex-col overflow-hidden rounded-xl! bg-popover p-1 text-popover-foreground", - className + className, )} {...props} /> - ) + ); } function CommandDialog({ @@ -41,11 +38,11 @@ function CommandDialog({ showCloseButton = false, ...props }: Omit, "children"> & { - title?: string - description?: string - className?: string - showCloseButton?: boolean - children: React.ReactNode + title?: string; + description?: string; + className?: string; + showCloseButton?: boolean; + children: React.ReactNode; }) { return ( @@ -56,14 +53,14 @@ function CommandDialog({ {children} - ) + ); } function CommandInput({ @@ -77,7 +74,7 @@ function CommandInput({ data-slot="command-input" className={cn( "w-full text-sm outline-hidden disabled:cursor-not-allowed disabled:opacity-50", - className + className, )} {...props} /> @@ -86,7 +83,7 @@ function CommandInput({
- ) + ); } function CommandList({ @@ -98,11 +95,11 @@ function CommandList({ data-slot="command-list" className={cn( "no-scrollbar max-h-72 scroll-py-1 overflow-x-hidden overflow-y-auto outline-none", - className + className, )} {...props} /> - ) + ); } function CommandEmpty({ @@ -115,7 +112,7 @@ function CommandEmpty({ className={cn("py-6 text-center text-sm", className)} {...props} /> - ) + ); } function CommandGroup({ @@ -127,11 +124,11 @@ function CommandGroup({ data-slot="command-group" className={cn( "overflow-hidden p-1 text-foreground **:[[cmdk-group-heading]]:px-2 **:[[cmdk-group-heading]]:py-1.5 **:[[cmdk-group-heading]]:text-xs **:[[cmdk-group-heading]]:font-medium **:[[cmdk-group-heading]]:text-muted-foreground", - className + className, )} {...props} /> - ) + ); } function CommandSeparator({ @@ -144,7 +141,7 @@ function CommandSeparator({ className={cn("-mx-1 h-px bg-border", className)} {...props} /> - ) + ); } function CommandItem({ @@ -157,14 +154,14 @@ function CommandItem({ data-slot="command-item" className={cn( "group/command-item relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none in-data-[slot=dialog-content]:rounded-lg! data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50 data-selected:bg-muted data-selected:text-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 data-selected:*:[svg]:text-foreground", - className + className, )} {...props} > {children} - ) + ); } function CommandShortcut({ @@ -176,11 +173,11 @@ function CommandShortcut({ data-slot="command-shortcut" className={cn( "ml-auto text-xs tracking-widest text-muted-foreground group-data-selected/command-item:text-foreground", - className + className, )} {...props} /> - ) + ); } export { @@ -193,4 +190,4 @@ export { CommandItem, CommandShortcut, CommandSeparator, -} +}; diff --git a/src/components/ui/context-menu.tsx b/src/components/ui/context-menu.tsx index 9c0eb98..91f82e4 100644 --- a/src/components/ui/context-menu.tsx +++ b/src/components/ui/context-menu.tsx @@ -1,19 +1,19 @@ -"use client" +"use client"; -import * as React from "react" -import { ContextMenu as ContextMenuPrimitive } from "@base-ui/react/context-menu" +import * as React from "react"; +import { ContextMenu as ContextMenuPrimitive } from "@base-ui/react/context-menu"; -import { cn } from "@/lib/utils" -import { ChevronRightIcon, CheckIcon } from "lucide-react" +import { cn } from "@/lib/utils"; +import { ChevronRightIcon, CheckIcon } from "lucide-react"; function ContextMenu({ ...props }: ContextMenuPrimitive.Root.Props) { - return + return ; } function ContextMenuPortal({ ...props }: ContextMenuPrimitive.Portal.Props) { return ( - ) + ); } function ContextMenuTrigger({ @@ -26,7 +26,7 @@ function ContextMenuTrigger({ className={cn("select-none", className)} {...props} /> - ) + ); } function ContextMenuContent({ @@ -52,18 +52,21 @@ function ContextMenuContent({ > - ) + ); } function ContextMenuGroup({ ...props }: ContextMenuPrimitive.Group.Props) { return ( - ) + ); } function ContextMenuLabel({ @@ -71,7 +74,7 @@ function ContextMenuLabel({ inset, ...props }: ContextMenuPrimitive.GroupLabel.Props & { - inset?: boolean + inset?: boolean; }) { return ( - ) + ); } function ContextMenuItem({ @@ -92,8 +95,8 @@ function ContextMenuItem({ variant = "default", ...props }: ContextMenuPrimitive.Item.Props & { - inset?: boolean - variant?: "default" | "destructive" + inset?: boolean; + variant?: "default" | "destructive"; }) { return ( - ) + ); } function ContextMenuSub({ ...props }: ContextMenuPrimitive.SubmenuRoot.Props) { return ( - ) + ); } function ContextMenuSubTrigger({ @@ -121,7 +124,7 @@ function ContextMenuSubTrigger({ children, ...props }: ContextMenuPrimitive.SubmenuTrigger.Props & { - inset?: boolean + inset?: boolean; }) { return ( {children} - ) + ); } function ContextMenuSubContent({ @@ -149,7 +152,7 @@ function ContextMenuSubContent({ side="right" {...props} /> - ) + ); } function ContextMenuCheckboxItem({ @@ -159,7 +162,7 @@ function ContextMenuCheckboxItem({ inset, ...props }: ContextMenuPrimitive.CheckboxItem.Props & { - inset?: boolean + inset?: boolean; }) { return ( - + {children} - ) + ); } function ContextMenuRadioGroup({ @@ -191,7 +193,7 @@ function ContextMenuRadioGroup({ data-slot="context-menu-radio-group" {...props} /> - ) + ); } function ContextMenuRadioItem({ @@ -200,7 +202,7 @@ function ContextMenuRadioItem({ inset, ...props }: ContextMenuPrimitive.RadioItem.Props & { - inset?: boolean + inset?: boolean; }) { return ( - + {children} - ) + ); } function ContextMenuSeparator({ @@ -233,7 +234,7 @@ function ContextMenuSeparator({ className={cn("-mx-1 my-1 h-px bg-border", className)} {...props} /> - ) + ); } function ContextMenuShortcut({ @@ -245,11 +246,11 @@ function ContextMenuShortcut({ data-slot="context-menu-shortcut" className={cn( "ml-auto text-xs tracking-widest text-muted-foreground group-focus/context-menu-item:text-accent-foreground", - className + className, )} {...props} /> - ) + ); } export { @@ -268,4 +269,4 @@ export { ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuRadioGroup, -} +}; diff --git a/src/components/ui/dialog.tsx b/src/components/ui/dialog.tsx index 014f5aa..308e17f 100644 --- a/src/components/ui/dialog.tsx +++ b/src/components/ui/dialog.tsx @@ -1,26 +1,26 @@ -"use client" +"use client"; -import * as React from "react" -import { Dialog as DialogPrimitive } from "@base-ui/react/dialog" +import * as React from "react"; +import { Dialog as DialogPrimitive } from "@base-ui/react/dialog"; -import { cn } from "@/lib/utils" -import { Button } from "@/components/ui/button" -import { XIcon } from "lucide-react" +import { cn } from "@/lib/utils"; +import { Button } from "@/components/ui/button"; +import { XIcon } from "lucide-react"; function Dialog({ ...props }: DialogPrimitive.Root.Props) { - return + return ; } function DialogTrigger({ ...props }: DialogPrimitive.Trigger.Props) { - return + return ; } function DialogPortal({ ...props }: DialogPrimitive.Portal.Props) { - return + return ; } function DialogClose({ ...props }: DialogPrimitive.Close.Props) { - return + return ; } function DialogOverlay({ @@ -32,11 +32,11 @@ function DialogOverlay({ data-slot="dialog-overlay" className={cn( "fixed inset-0 isolate z-50 bg-black/10 duration-100 supports-backdrop-filter:backdrop-blur-xs data-open:animate-in data-open:fade-in-0 data-closed:animate-out data-closed:fade-out-0", - className + className, )} {...props} /> - ) + ); } function DialogContent({ @@ -45,7 +45,7 @@ function DialogContent({ showCloseButton = true, ...props }: DialogPrimitive.Popup.Props & { - showCloseButton?: boolean + showCloseButton?: boolean; }) { return ( @@ -54,7 +54,7 @@ function DialogContent({ data-slot="dialog-content" className={cn( "fixed top-1/2 left-1/2 z-50 grid w-full max-w-[calc(100%-2rem)] -translate-x-1/2 -translate-y-1/2 gap-4 rounded-xl bg-popover p-4 text-sm text-popover-foreground ring-1 ring-foreground/10 duration-100 outline-none sm:max-w-sm data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95", - className + className, )} {...props} > @@ -70,14 +70,13 @@ function DialogContent({ /> } > - + Close )} - ) + ); } function DialogHeader({ className, ...props }: React.ComponentProps<"div">) { @@ -87,7 +86,7 @@ function DialogHeader({ className, ...props }: React.ComponentProps<"div">) { className={cn("flex flex-col gap-2", className)} {...props} /> - ) + ); } function DialogFooter({ @@ -96,14 +95,14 @@ function DialogFooter({ children, ...props }: React.ComponentProps<"div"> & { - showCloseButton?: boolean + showCloseButton?: boolean; }) { return (
@@ -114,7 +113,7 @@ function DialogFooter({ )}
- ) + ); } function DialogTitle({ className, ...props }: DialogPrimitive.Title.Props) { @@ -123,11 +122,11 @@ function DialogTitle({ className, ...props }: DialogPrimitive.Title.Props) { data-slot="dialog-title" className={cn( "font-heading text-base leading-none font-medium", - className + className, )} {...props} /> - ) + ); } function DialogDescription({ @@ -139,11 +138,11 @@ function DialogDescription({ data-slot="dialog-description" className={cn( "text-sm text-muted-foreground *:[a]:underline *:[a]:underline-offset-3 *:[a]:hover:text-foreground", - className + className, )} {...props} /> - ) + ); } export { @@ -157,4 +156,4 @@ export { DialogPortal, DialogTitle, DialogTrigger, -} +}; diff --git a/src/components/ui/direction.tsx b/src/components/ui/direction.tsx index d8cf134..0926874 100644 --- a/src/components/ui/direction.tsx +++ b/src/components/ui/direction.tsx @@ -1,6 +1,6 @@ -"use client" +"use client"; export { DirectionProvider, useDirection, -} from "@base-ui/react/direction-provider" +} from "@base-ui/react/direction-provider"; diff --git a/src/components/ui/drawer.tsx b/src/components/ui/drawer.tsx index bde74ac..9cdfe7c 100644 --- a/src/components/ui/drawer.tsx +++ b/src/components/ui/drawer.tsx @@ -1,27 +1,27 @@ -"use client" +"use client"; -import * as React from "react" -import { Drawer as DrawerPrimitive } from "@base-ui/react/drawer" +import * as React from "react"; +import { Drawer as DrawerPrimitive } from "@base-ui/react/drawer"; -import { cn } from "@/lib/utils" +import { cn } from "@/lib/utils"; type DrawerContextProps = { - hasSnapPoints: boolean - modal: DrawerPrimitive.Root.Props["modal"] - showSwipeHandle: boolean - swipeDirection: NonNullable -} + hasSnapPoints: boolean; + modal: DrawerPrimitive.Root.Props["modal"]; + showSwipeHandle: boolean; + swipeDirection: NonNullable; +}; -const DrawerContext = React.createContext(null) +const DrawerContext = React.createContext(null); function useDrawer() { - const context = React.useContext(DrawerContext) + const context = React.useContext(DrawerContext); if (!context) { - throw new Error("useDrawer must be used within a Drawer.") + throw new Error("useDrawer must be used within a Drawer."); } - return context + return context; } function Drawer({ @@ -31,13 +31,13 @@ function Drawer({ swipeDirection = "down", ...props }: DrawerPrimitive.Root.Props & { - showSwipeHandle?: boolean + showSwipeHandle?: boolean; }) { - const hasSnapPoints = snapPoints != null && snapPoints.length > 0 + const hasSnapPoints = snapPoints != null && snapPoints.length > 0; const contextValue = React.useMemo( () => ({ hasSnapPoints, modal, showSwipeHandle, swipeDirection }), - [hasSnapPoints, modal, showSwipeHandle, swipeDirection] - ) + [hasSnapPoints, modal, showSwipeHandle, swipeDirection], + ); return ( @@ -49,19 +49,19 @@ function Drawer({ {...props} /> - ) + ); } function DrawerTrigger({ ...props }: DrawerPrimitive.Trigger.Props) { - return + return ; } function DrawerPortal({ ...props }: DrawerPrimitive.Portal.Props) { - return + return ; } function DrawerClose({ ...props }: DrawerPrimitive.Close.Props) { - return + return ; } function DrawerOverlay({ @@ -73,11 +73,11 @@ function DrawerOverlay({ data-slot="drawer-overlay" className={cn( "fixed inset-0 z-50 min-h-dvh bg-black/10 opacity-[max(var(--drawer-overlay-min-opacity,0),calc(1-var(--drawer-swipe-progress)))] transition-opacity duration-450 ease-[cubic-bezier(0.32,0.72,0,1)] select-none data-ending-style:pointer-events-none data-ending-style:opacity-0 data-ending-style:duration-[calc(var(--drawer-swipe-strength)*400ms)] data-snap-points:[--drawer-overlay-min-opacity:0.5] data-starting-style:opacity-0 data-swiping:duration-0 supports-backdrop-filter:backdrop-blur-xs supports-[-webkit-touch-callout:none]:absolute", - className + className, )} {...props} /> - ) + ); } function DrawerSwipeHandle({ @@ -90,11 +90,11 @@ function DrawerSwipeHandle({ aria-hidden="true" className={cn( "relative z-10 flex shrink-0 cursor-grab transition-opacity duration-200 group-data-nested-drawer-open/drawer-popup:opacity-0 group-data-nested-drawer-swiping/drawer-popup:opacity-100 group-data-[swipe-axis=x]/drawer-popup:h-full group-data-[swipe-axis=x]/drawer-popup:w-3 group-data-[swipe-axis=x]/drawer-popup:items-center group-data-[swipe-axis=y]/drawer-popup:h-3 group-data-[swipe-axis=y]/drawer-popup:w-full group-data-[swipe-axis=y]/drawer-popup:justify-center group-data-[swipe-direction=down]/drawer-popup:items-end group-data-[swipe-direction=left]/drawer-popup:order-last group-data-[swipe-direction=left]/drawer-popup:justify-start group-data-[swipe-direction=right]/drawer-popup:justify-end group-data-[swipe-direction=up]/drawer-popup:order-last group-data-[swipe-direction=up]/drawer-popup:items-start after:block after:shrink-0 after:rounded-full after:bg-muted group-data-[swipe-axis=x]/drawer-popup:after:h-24 group-data-[swipe-axis=x]/drawer-popup:after:w-1 group-data-[swipe-axis=y]/drawer-popup:after:h-1 group-data-[swipe-axis=y]/drawer-popup:after:w-24 active:cursor-grabbing", - className + className, )} {...props} /> - ) + ); } function DrawerContent({ @@ -102,9 +102,9 @@ function DrawerContent({ children, ...props }: DrawerPrimitive.Popup.Props) { - const { hasSnapPoints, modal, showSwipeHandle, swipeDirection } = useDrawer() + const { hasSnapPoints, modal, showSwipeHandle, swipeDirection } = useDrawer(); const swipeAxis = - swipeDirection === "down" || swipeDirection === "up" ? "y" : "x" + swipeDirection === "down" || swipeDirection === "up" ? "y" : "x"; return ( @@ -145,7 +145,7 @@ function DrawerContent({ "data-[swipe-direction=left]:left-0 data-[swipe-direction=left]:origin-left data-[swipe-direction=left]:[--closed-transform:translate3d(calc(-100%-var(--drawer-inset,0px)-2px),0,0)] data-[swipe-direction=left]:[--translate-x:calc(var(--drawer-swipe-movement-x)+var(--stack-peek-offset)+(var(--stack-shrink)*100%))]", // Direction: right. "data-[swipe-direction=right]:right-0 data-[swipe-direction=right]:origin-right data-[swipe-direction=right]:[--closed-transform:translate3d(calc(100%+var(--drawer-inset,0px)+2px),0,0)] data-[swipe-direction=right]:[--translate-x:calc(var(--drawer-swipe-movement-x)-var(--stack-peek-offset)-(var(--stack-shrink)*100%))]", - className + className, )} {...props} > @@ -153,7 +153,7 @@ function DrawerContent({ {children} @@ -161,7 +161,7 @@ function DrawerContent({ - ) + ); } function DrawerHeader({ className, ...props }: React.ComponentProps<"div">) { @@ -170,11 +170,11 @@ function DrawerHeader({ className, ...props }: React.ComponentProps<"div">) { data-slot="drawer-header" className={cn( "flex shrink-0 flex-col gap-0.5 p-4 pb-0 group-data-[swipe-axis=y]/drawer-popup:text-center md:gap-0.5 md:text-left", - className + className, )} {...props} /> - ) + ); } function DrawerFooter({ className, ...props }: React.ComponentProps<"div">) { @@ -184,7 +184,7 @@ function DrawerFooter({ className, ...props }: React.ComponentProps<"div">) { className={cn("mt-auto flex shrink-0 flex-col gap-2 p-4 pt-0", className)} {...props} /> - ) + ); } function DrawerTitle({ className, ...props }: DrawerPrimitive.Title.Props) { @@ -193,11 +193,11 @@ function DrawerTitle({ className, ...props }: DrawerPrimitive.Title.Props) { data-slot="drawer-title" className={cn( "font-heading text-base font-medium text-foreground", - className + className, )} {...props} /> - ) + ); } function DrawerDescription({ @@ -210,7 +210,7 @@ function DrawerDescription({ className={cn("text-sm text-balance text-muted-foreground", className)} {...props} /> - ) + ); } export { @@ -225,4 +225,4 @@ export { DrawerFooter, DrawerTitle, DrawerDescription, -} +}; diff --git a/src/components/ui/dropdown-menu.tsx b/src/components/ui/dropdown-menu.tsx index 9d5ebbd..0d67f0d 100644 --- a/src/components/ui/dropdown-menu.tsx +++ b/src/components/ui/dropdown-menu.tsx @@ -1,21 +1,21 @@ -"use client" +"use client"; -import * as React from "react" -import { Menu as MenuPrimitive } from "@base-ui/react/menu" +import * as React from "react"; +import { Menu as MenuPrimitive } from "@base-ui/react/menu"; -import { cn } from "@/lib/utils" -import { ChevronRightIcon, CheckIcon } from "lucide-react" +import { cn } from "@/lib/utils"; +import { ChevronRightIcon, CheckIcon } from "lucide-react"; function DropdownMenu({ ...props }: MenuPrimitive.Root.Props) { - return + return ; } function DropdownMenuPortal({ ...props }: MenuPrimitive.Portal.Props) { - return + return ; } function DropdownMenuTrigger({ ...props }: MenuPrimitive.Trigger.Props) { - return + return ; } function DropdownMenuContent({ @@ -41,16 +41,19 @@ function DropdownMenuContent({ > - ) + ); } function DropdownMenuGroup({ ...props }: MenuPrimitive.Group.Props) { - return + return ; } function DropdownMenuLabel({ @@ -58,7 +61,7 @@ function DropdownMenuLabel({ inset, ...props }: MenuPrimitive.GroupLabel.Props & { - inset?: boolean + inset?: boolean; }) { return ( - ) + ); } function DropdownMenuItem({ @@ -79,8 +82,8 @@ function DropdownMenuItem({ variant = "default", ...props }: MenuPrimitive.Item.Props & { - inset?: boolean - variant?: "default" | "destructive" + inset?: boolean; + variant?: "default" | "destructive"; }) { return ( - ) + ); } function DropdownMenuSub({ ...props }: MenuPrimitive.SubmenuRoot.Props) { - return + return ; } function DropdownMenuSubTrigger({ @@ -106,7 +109,7 @@ function DropdownMenuSubTrigger({ children, ...props }: MenuPrimitive.SubmenuTrigger.Props & { - inset?: boolean + inset?: boolean; }) { return ( {children} - ) + ); } function DropdownMenuSubContent({ @@ -135,14 +138,17 @@ function DropdownMenuSubContent({ return ( - ) + ); } function DropdownMenuCheckboxItem({ @@ -152,7 +158,7 @@ function DropdownMenuCheckboxItem({ inset, ...props }: MenuPrimitive.CheckboxItem.Props & { - inset?: boolean + inset?: boolean; }) { return ( - +
{children} - ) + ); } function DropdownMenuRadioGroup({ ...props }: MenuPrimitive.RadioGroup.Props) { @@ -185,7 +190,7 @@ function DropdownMenuRadioGroup({ ...props }: MenuPrimitive.RadioGroup.Props) { data-slot="dropdown-menu-radio-group" {...props} /> - ) + ); } function DropdownMenuRadioItem({ @@ -194,7 +199,7 @@ function DropdownMenuRadioItem({ inset, ...props }: MenuPrimitive.RadioItem.Props & { - inset?: boolean + inset?: boolean; }) { return ( @@ -211,13 +216,12 @@ function DropdownMenuRadioItem({ data-slot="dropdown-menu-radio-item-indicator" > - +
{children} - ) + ); } function DropdownMenuSeparator({ @@ -230,7 +234,7 @@ function DropdownMenuSeparator({ className={cn("-mx-1 my-1 h-px bg-border", className)} {...props} /> - ) + ); } function DropdownMenuShortcut({ @@ -242,11 +246,11 @@ function DropdownMenuShortcut({ data-slot="dropdown-menu-shortcut" className={cn( "ml-auto text-xs tracking-widest text-muted-foreground group-focus/dropdown-menu-item:text-accent-foreground", - className + className, )} {...props} /> - ) + ); } export { @@ -265,4 +269,4 @@ export { DropdownMenuSub, DropdownMenuSubTrigger, DropdownMenuSubContent, -} +}; diff --git a/src/components/ui/empty.tsx b/src/components/ui/empty.tsx index b23187b..c58117a 100644 --- a/src/components/ui/empty.tsx +++ b/src/components/ui/empty.tsx @@ -1,6 +1,6 @@ -import { cva, type VariantProps } from "class-variance-authority" +import { cva, type VariantProps } from "class-variance-authority"; -import { cn } from "@/lib/utils" +import { cn } from "@/lib/utils"; function Empty({ className, ...props }: React.ComponentProps<"div">) { return ( @@ -8,11 +8,11 @@ function Empty({ className, ...props }: React.ComponentProps<"div">) { data-slot="empty" className={cn( "flex w-full min-w-0 flex-1 flex-col items-center justify-center gap-4 rounded-xl border-dashed p-6 text-center text-balance", - className + className, )} {...props} /> - ) + ); } function EmptyHeader({ className, ...props }: React.ComponentProps<"div">) { @@ -22,7 +22,7 @@ function EmptyHeader({ className, ...props }: React.ComponentProps<"div">) { className={cn("flex max-w-sm flex-col items-center gap-2", className)} {...props} /> - ) + ); } const emptyMediaVariants = cva( @@ -37,8 +37,8 @@ const emptyMediaVariants = cva( defaultVariants: { variant: "default", }, - } -) + }, +); function EmptyMedia({ className, @@ -52,7 +52,7 @@ function EmptyMedia({ className={cn(emptyMediaVariants({ variant, className }))} {...props} /> - ) + ); } function EmptyTitle({ className, ...props }: React.ComponentProps<"div">) { @@ -61,11 +61,11 @@ function EmptyTitle({ className, ...props }: React.ComponentProps<"div">) { data-slot="empty-title" className={cn( "font-heading text-sm font-medium tracking-tight", - className + className, )} {...props} /> - ) + ); } function EmptyDescription({ className, ...props }: React.ComponentProps<"p">) { @@ -74,11 +74,11 @@ function EmptyDescription({ className, ...props }: React.ComponentProps<"p">) { data-slot="empty-description" className={cn( "text-sm/relaxed text-muted-foreground [&>a]:underline [&>a]:underline-offset-4 [&>a:hover]:text-primary", - className + className, )} {...props} /> - ) + ); } function EmptyContent({ className, ...props }: React.ComponentProps<"div">) { @@ -87,11 +87,11 @@ function EmptyContent({ className, ...props }: React.ComponentProps<"div">) { data-slot="empty-content" className={cn( "flex w-full max-w-sm min-w-0 flex-col items-center gap-2.5 text-sm text-balance", - className + className, )} {...props} /> - ) + ); } export { @@ -101,4 +101,4 @@ export { EmptyDescription, EmptyContent, EmptyMedia, -} +}; diff --git a/src/components/ui/field.tsx b/src/components/ui/field.tsx index 2bc5bb6..9871b0d 100644 --- a/src/components/ui/field.tsx +++ b/src/components/ui/field.tsx @@ -1,11 +1,11 @@ -"use client" +"use client"; -import { useMemo } from "react" -import { cva, type VariantProps } from "class-variance-authority" +import { useMemo } from "react"; +import { cva, type VariantProps } from "class-variance-authority"; -import { cn } from "@/lib/utils" -import { Label } from "@/components/ui/label" -import { Separator } from "@/components/ui/separator" +import { cn } from "@/lib/utils"; +import { Label } from "@/components/ui/label"; +import { Separator } from "@/components/ui/separator"; function FieldSet({ className, ...props }: React.ComponentProps<"fieldset">) { return ( @@ -13,11 +13,11 @@ function FieldSet({ className, ...props }: React.ComponentProps<"fieldset">) { data-slot="field-set" className={cn( "flex flex-col gap-4 has-[>[data-slot=checkbox-group]]:gap-3 has-[>[data-slot=radio-group]]:gap-3", - className + className, )} {...props} /> - ) + ); } function FieldLegend({ @@ -31,11 +31,11 @@ function FieldLegend({ data-variant={variant} className={cn( "mb-1.5 font-medium data-[variant=label]:text-sm data-[variant=legend]:text-base", - className + className, )} {...props} /> - ) + ); } function FieldGroup({ className, ...props }: React.ComponentProps<"div">) { @@ -44,11 +44,11 @@ function FieldGroup({ className, ...props }: React.ComponentProps<"div">) { data-slot="field-group" className={cn( "group/field-group @container/field-group flex w-full flex-col gap-5 data-[slot=checkbox-group]:gap-3 *:data-[slot=field-group]:gap-4", - className + className, )} {...props} /> - ) + ); } const fieldVariants = cva( @@ -66,8 +66,8 @@ const fieldVariants = cva( defaultVariants: { orientation: "vertical", }, - } -) + }, +); function Field({ className, @@ -82,7 +82,7 @@ function Field({ className={cn(fieldVariants({ orientation }), className)} {...props} /> - ) + ); } function FieldContent({ className, ...props }: React.ComponentProps<"div">) { @@ -91,11 +91,11 @@ function FieldContent({ className, ...props }: React.ComponentProps<"div">) { data-slot="field-content" className={cn( "group/field-content flex flex-1 flex-col gap-0.5 leading-snug", - className + className, )} {...props} /> - ) + ); } function FieldLabel({ @@ -108,11 +108,11 @@ function FieldLabel({ className={cn( "group/field-label peer/field-label flex w-fit gap-2 leading-snug group-data-[disabled=true]/field:opacity-50 has-data-checked:border-primary/30 has-data-checked:bg-primary/5 has-[>[data-slot=field]]:rounded-lg has-[>[data-slot=field]]:border *:data-[slot=field]:p-2.5 dark:has-data-checked:border-primary/20 dark:has-data-checked:bg-primary/10", "has-[>[data-slot=field]]:w-full has-[>[data-slot=field]]:flex-col", - className + className, )} {...props} /> - ) + ); } function FieldTitle({ className, ...props }: React.ComponentProps<"div">) { @@ -121,11 +121,11 @@ function FieldTitle({ className, ...props }: React.ComponentProps<"div">) { data-slot="field-label" className={cn( "flex w-fit items-center gap-2 text-sm font-medium group-data-[disabled=true]/field:opacity-50", - className + className, )} {...props} /> - ) + ); } function FieldDescription({ className, ...props }: React.ComponentProps<"p">) { @@ -136,11 +136,11 @@ function FieldDescription({ className, ...props }: React.ComponentProps<"p">) { "text-left text-sm leading-normal font-normal text-muted-foreground group-has-data-horizontal/field:text-balance [[data-variant=legend]+&]:-mt-1.5", "last:mt-0 nth-last-2:-mt-1", "[&>a]:underline [&>a]:underline-offset-4 [&>a:hover]:text-primary", - className + className, )} {...props} /> - ) + ); } function FieldSeparator({ @@ -148,7 +148,7 @@ function FieldSeparator({ className, ...props }: React.ComponentProps<"div"> & { - children?: React.ReactNode + children?: React.ReactNode; }) { return (
@@ -170,7 +170,7 @@ function FieldSeparator({ )}
- ) + ); } function FieldError({ @@ -179,37 +179,37 @@ function FieldError({ errors, ...props }: React.ComponentProps<"div"> & { - errors?: Array<{ message?: string } | undefined> + errors?: Array<{ message?: string } | undefined>; }) { const content = useMemo(() => { if (children) { - return children + return children; } if (!errors?.length) { - return null + return null; } const uniqueErrors = [ ...new Map(errors.map((error) => [error?.message, error])).values(), - ] + ]; if (uniqueErrors?.length == 1) { - return uniqueErrors[0]?.message + return uniqueErrors[0]?.message; } return (
    {uniqueErrors.map( (error, index) => - error?.message &&
  • {error.message}
  • + error?.message &&
  • {error.message}
  • , )}
- ) - }, [children, errors]) + ); + }, [children, errors]); if (!content) { - return null + return null; } return ( @@ -221,7 +221,7 @@ function FieldError({ > {content}
- ) + ); } export { @@ -235,4 +235,4 @@ export { FieldSet, FieldContent, FieldTitle, -} +}; diff --git a/src/components/ui/hover-card.tsx b/src/components/ui/hover-card.tsx index 58a477c..a3b1781 100644 --- a/src/components/ui/hover-card.tsx +++ b/src/components/ui/hover-card.tsx @@ -1,17 +1,17 @@ -"use client" +"use client"; -import { PreviewCard as PreviewCardPrimitive } from "@base-ui/react/preview-card" +import { PreviewCard as PreviewCardPrimitive } from "@base-ui/react/preview-card"; -import { cn } from "@/lib/utils" +import { cn } from "@/lib/utils"; function HoverCard({ ...props }: PreviewCardPrimitive.Root.Props) { - return + return ; } function HoverCardTrigger({ ...props }: PreviewCardPrimitive.Trigger.Props) { return ( - ) + ); } function HoverCardContent({ @@ -39,13 +39,13 @@ function HoverCardContent({ data-slot="hover-card-content" className={cn( "z-50 w-64 origin-(--transform-origin) rounded-lg bg-popover p-2.5 text-sm text-popover-foreground shadow-md ring-1 ring-foreground/10 outline-hidden duration-100 data-[side=bottom]:slide-in-from-top-2 data-[side=inline-end]:slide-in-from-left-2 data-[side=inline-start]:slide-in-from-right-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 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95", - className + className, )} {...props} /> - ) + ); } -export { HoverCard, HoverCardTrigger, HoverCardContent } +export { HoverCard, HoverCardTrigger, HoverCardContent }; diff --git a/src/components/ui/input-group.tsx b/src/components/ui/input-group.tsx index da8f1dd..5e8caf2 100644 --- a/src/components/ui/input-group.tsx +++ b/src/components/ui/input-group.tsx @@ -1,12 +1,12 @@ -"use client" +"use client"; -import * as React from "react" -import { cva, type VariantProps } from "class-variance-authority" +import * as React from "react"; +import { cva, type VariantProps } from "class-variance-authority"; -import { cn } from "@/lib/utils" -import { Button } from "@/components/ui/button" -import { Input } from "@/components/ui/input" -import { Textarea } from "@/components/ui/textarea" +import { cn } from "@/lib/utils"; +import { Button } from "@/components/ui/button"; +import { Input } from "@/components/ui/input"; +import { Textarea } from "@/components/ui/textarea"; function InputGroup({ className, ...props }: React.ComponentProps<"div">) { return ( @@ -15,11 +15,11 @@ function InputGroup({ className, ...props }: React.ComponentProps<"div">) { role="group" className={cn( "group/input-group relative flex h-8 w-full min-w-0 items-center rounded-lg border border-input transition-colors outline-none in-data-[slot=combobox-content]:focus-within:border-inherit in-data-[slot=combobox-content]:focus-within:ring-0 has-disabled:bg-input/50 has-disabled:opacity-50 has-[[data-slot=input-group-control]:focus-visible]:border-ring has-[[data-slot=input-group-control]:focus-visible]:ring-3 has-[[data-slot=input-group-control]:focus-visible]:ring-ring/50 has-[[data-slot][aria-invalid=true]]:border-destructive has-[[data-slot][aria-invalid=true]]:ring-3 has-[[data-slot][aria-invalid=true]]:ring-destructive/20 has-[>[data-align=block-end]]:h-auto has-[>[data-align=block-end]]:flex-col has-[>[data-align=block-start]]:h-auto has-[>[data-align=block-start]]:flex-col has-[>textarea]:h-auto dark:bg-input/30 dark:has-disabled:bg-input/80 dark:has-[[data-slot][aria-invalid=true]]:ring-destructive/40 has-[>[data-align=block-end]]:[&>input]:pt-3 has-[>[data-align=block-start]]:[&>input]:pb-3 has-[>[data-align=inline-end]]:[&>input]:pr-1.5 has-[>[data-align=inline-start]]:[&>input]:pl-1.5", - className + className, )} {...props} /> - ) + ); } const inputGroupAddonVariants = cva( @@ -40,8 +40,8 @@ const inputGroupAddonVariants = cva( defaultVariants: { align: "inline-start", }, - } -) + }, +); function InputGroupAddon({ className, @@ -56,13 +56,13 @@ function InputGroupAddon({ className={cn(inputGroupAddonVariants({ align }), className)} onClick={(e) => { if ((e.target as HTMLElement).closest("button")) { - return + return; } - e.currentTarget.parentElement?.querySelector("input")?.focus() + e.currentTarget.parentElement?.querySelector("input")?.focus(); }} {...props} /> - ) + ); } const inputGroupButtonVariants = cva( @@ -80,8 +80,8 @@ const inputGroupButtonVariants = cva( defaultVariants: { size: "xs", }, - } -) + }, +); function InputGroupButton({ className, @@ -91,7 +91,7 @@ function InputGroupButton({ ...props }: Omit, "size" | "type"> & VariantProps & { - type?: "button" | "submit" | "reset" + type?: "button" | "submit" | "reset"; }) { return (
- ) + ); } function InputOTPSeparator({ ...props }: React.ComponentProps<"div">) { @@ -78,10 +78,9 @@ function InputOTPSeparator({ ...props }: React.ComponentProps<"div">) { role="separator" {...props} > - + - ) + ); } -export { InputOTP, InputOTPGroup, InputOTPSlot, InputOTPSeparator } +export { InputOTP, InputOTPGroup, InputOTPSlot, InputOTPSeparator }; diff --git a/src/components/ui/input.tsx b/src/components/ui/input.tsx index 7d21bab..abb87eb 100644 --- a/src/components/ui/input.tsx +++ b/src/components/ui/input.tsx @@ -1,7 +1,7 @@ -import * as React from "react" -import { Input as InputPrimitive } from "@base-ui/react/input" +import * as React from "react"; +import { Input as InputPrimitive } from "@base-ui/react/input"; -import { cn } from "@/lib/utils" +import { cn } from "@/lib/utils"; function Input({ className, type, ...props }: React.ComponentProps<"input">) { return ( @@ -10,11 +10,11 @@ function Input({ className, type, ...props }: React.ComponentProps<"input">) { data-slot="input" className={cn( "h-8 w-full min-w-0 rounded-lg border border-input bg-transparent px-2.5 py-1 text-base transition-colors outline-none file:inline-flex file:h-6 file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:pointer-events-none disabled:cursor-not-allowed disabled:bg-input/50 disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 md:text-sm dark:bg-input/30 dark:disabled:bg-input/80 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40", - className + className, )} {...props} /> - ) + ); } -export { Input } +export { Input }; diff --git a/src/components/ui/item.tsx b/src/components/ui/item.tsx index 0f872ee..c6d9df2 100644 --- a/src/components/ui/item.tsx +++ b/src/components/ui/item.tsx @@ -1,10 +1,10 @@ -import * as React from "react" -import { mergeProps } from "@base-ui/react/merge-props" -import { useRender } from "@base-ui/react/use-render" -import { cva, type VariantProps } from "class-variance-authority" +import * as React from "react"; +import { mergeProps } from "@base-ui/react/merge-props"; +import { useRender } from "@base-ui/react/use-render"; +import { cva, type VariantProps } from "class-variance-authority"; -import { cn } from "@/lib/utils" -import { Separator } from "@/components/ui/separator" +import { cn } from "@/lib/utils"; +import { Separator } from "@/components/ui/separator"; function ItemGroup({ className, ...props }: React.ComponentProps<"div">) { return ( @@ -13,11 +13,11 @@ function ItemGroup({ className, ...props }: React.ComponentProps<"div">) { data-slot="item-group" className={cn( "group/item-group flex w-full flex-col gap-4 has-data-[size=sm]:gap-2.5 has-data-[size=xs]:gap-2", - className + className, )} {...props} /> - ) + ); } function ItemSeparator({ @@ -31,7 +31,7 @@ function ItemSeparator({ className={cn("my-2", className)} {...props} /> - ) + ); } const itemVariants = cva( @@ -53,8 +53,8 @@ const itemVariants = cva( variant: "default", size: "default", }, - } -) + }, +); function Item({ className, @@ -69,7 +69,7 @@ function Item({ { className: cn(itemVariants({ variant, size, className })), }, - props + props, ), render, state: { @@ -77,7 +77,7 @@ function Item({ variant, size, }, - }) + }); } const itemMediaVariants = cva( @@ -94,8 +94,8 @@ const itemMediaVariants = cva( defaultVariants: { variant: "default", }, - } -) + }, +); function ItemMedia({ className, @@ -109,7 +109,7 @@ function ItemMedia({ className={cn(itemMediaVariants({ variant, className }))} {...props} /> - ) + ); } function ItemContent({ className, ...props }: React.ComponentProps<"div">) { @@ -118,11 +118,11 @@ function ItemContent({ className, ...props }: React.ComponentProps<"div">) { data-slot="item-content" className={cn( "flex flex-1 flex-col gap-1 group-data-[size=xs]/item:gap-0 [&+[data-slot=item-content]]:flex-none", - className + className, )} {...props} /> - ) + ); } function ItemTitle({ className, ...props }: React.ComponentProps<"div">) { @@ -131,11 +131,11 @@ function ItemTitle({ className, ...props }: React.ComponentProps<"div">) { data-slot="item-title" className={cn( "line-clamp-1 flex w-fit items-center gap-2 text-sm leading-snug font-medium underline-offset-4", - className + className, )} {...props} /> - ) + ); } function ItemDescription({ className, ...props }: React.ComponentProps<"p">) { @@ -144,11 +144,11 @@ function ItemDescription({ className, ...props }: React.ComponentProps<"p">) { data-slot="item-description" className={cn( "line-clamp-2 text-left text-sm leading-normal font-normal text-muted-foreground group-data-[size=xs]/item:text-xs [&>a]:underline [&>a]:underline-offset-4 [&>a:hover]:text-primary", - className + className, )} {...props} /> - ) + ); } function ItemActions({ className, ...props }: React.ComponentProps<"div">) { @@ -158,7 +158,7 @@ function ItemActions({ className, ...props }: React.ComponentProps<"div">) { className={cn("flex items-center gap-2", className)} {...props} /> - ) + ); } function ItemHeader({ className, ...props }: React.ComponentProps<"div">) { @@ -167,11 +167,11 @@ function ItemHeader({ className, ...props }: React.ComponentProps<"div">) { data-slot="item-header" className={cn( "flex basis-full items-center justify-between gap-2", - className + className, )} {...props} /> - ) + ); } function ItemFooter({ className, ...props }: React.ComponentProps<"div">) { @@ -180,11 +180,11 @@ function ItemFooter({ className, ...props }: React.ComponentProps<"div">) { data-slot="item-footer" className={cn( "flex basis-full items-center justify-between gap-2", - className + className, )} {...props} /> - ) + ); } export { @@ -198,4 +198,4 @@ export { ItemDescription, ItemHeader, ItemFooter, -} +}; diff --git a/src/components/ui/kbd.tsx b/src/components/ui/kbd.tsx index ff93b53..44df653 100644 --- a/src/components/ui/kbd.tsx +++ b/src/components/ui/kbd.tsx @@ -1,4 +1,4 @@ -import { cn } from "@/lib/utils" +import { cn } from "@/lib/utils"; function Kbd({ className, ...props }: React.ComponentProps<"kbd">) { return ( @@ -6,11 +6,11 @@ function Kbd({ className, ...props }: React.ComponentProps<"kbd">) { data-slot="kbd" className={cn( "pointer-events-none inline-flex h-5 w-fit min-w-5 items-center justify-center gap-1 rounded-sm bg-muted px-1 font-sans text-xs font-medium text-muted-foreground select-none in-data-[slot=tooltip-content]:bg-background/20 in-data-[slot=tooltip-content]:text-background dark:in-data-[slot=tooltip-content]:bg-background/10 [&_svg:not([class*='size-'])]:size-3", - className + className, )} {...props} /> - ) + ); } function KbdGroup({ className, ...props }: React.ComponentProps<"div">) { @@ -20,7 +20,7 @@ function KbdGroup({ className, ...props }: React.ComponentProps<"div">) { className={cn("inline-flex items-center gap-1", className)} {...props} /> - ) + ); } -export { Kbd, KbdGroup } +export { Kbd, KbdGroup }; diff --git a/src/components/ui/label.tsx b/src/components/ui/label.tsx index 74da65c..680d9a6 100644 --- a/src/components/ui/label.tsx +++ b/src/components/ui/label.tsx @@ -1,8 +1,8 @@ -"use client" +"use client"; -import * as React from "react" +import * as React from "react"; -import { cn } from "@/lib/utils" +import { cn } from "@/lib/utils"; function Label({ className, ...props }: React.ComponentProps<"label">) { return ( @@ -10,11 +10,11 @@ function Label({ className, ...props }: React.ComponentProps<"label">) { data-slot="label" className={cn( "flex items-center gap-2 text-sm leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50", - className + className, )} {...props} /> - ) + ); } -export { Label } +export { Label }; diff --git a/src/components/ui/marker.tsx b/src/components/ui/marker.tsx index f59cca4..373afbe 100644 --- a/src/components/ui/marker.tsx +++ b/src/components/ui/marker.tsx @@ -1,9 +1,9 @@ -import * as React from "react" -import { mergeProps } from "@base-ui/react/merge-props" -import { useRender } from "@base-ui/react/use-render" -import { cva, type VariantProps } from "class-variance-authority" +import * as React from "react"; +import { mergeProps } from "@base-ui/react/merge-props"; +import { useRender } from "@base-ui/react/use-render"; +import { cva, type VariantProps } from "class-variance-authority"; -import { cn } from "@/lib/utils" +import { cn } from "@/lib/utils"; const markerVariants = cva( "group/marker relative flex min-h-4 w-full items-center gap-2 text-left text-sm text-muted-foreground [&_svg:not([class*='size-'])]:size-4 [a]:underline [a]:underline-offset-3 [a]:hover:text-foreground", @@ -16,8 +16,8 @@ const markerVariants = cva( border: "border-b border-border pb-2", }, }, - } -) + }, +); function Marker({ className, @@ -31,14 +31,14 @@ function Marker({ { className: cn(markerVariants({ variant, className })), }, - props + props, ), render, state: { slot: "marker", variant, }, - }) + }); } function MarkerIcon({ className, ...props }: React.ComponentProps<"span">) { @@ -48,11 +48,11 @@ function MarkerIcon({ className, ...props }: React.ComponentProps<"span">) { aria-hidden="true" className={cn( "size-4 shrink-0 [&_svg:not([class*='size-'])]:size-4", - className + className, )} {...props} /> - ) + ); } function MarkerContent({ className, ...props }: React.ComponentProps<"span">) { @@ -61,11 +61,11 @@ function MarkerContent({ className, ...props }: React.ComponentProps<"span">) { data-slot="marker-content" className={cn( "min-w-0 wrap-break-word group-data-[variant=separator]/marker:flex-none group-data-[variant=separator]/marker:text-center *:[a]:underline *:[a]:underline-offset-3 *:[a]:hover:text-foreground", - className + className, )} {...props} /> - ) + ); } -export { Marker, MarkerIcon, MarkerContent, markerVariants } +export { Marker, MarkerIcon, MarkerContent, markerVariants }; diff --git a/src/components/ui/menubar.tsx b/src/components/ui/menubar.tsx index 9738fb1..332735a 100644 --- a/src/components/ui/menubar.tsx +++ b/src/components/ui/menubar.tsx @@ -1,10 +1,10 @@ -"use client" +"use client"; -import * as React from "react" -import { Menu as MenuPrimitive } from "@base-ui/react/menu" -import { Menubar as MenubarPrimitive } from "@base-ui/react/menubar" +import * as React from "react"; +import { Menu as MenuPrimitive } from "@base-ui/react/menu"; +import { Menubar as MenubarPrimitive } from "@base-ui/react/menubar"; -import { cn } from "@/lib/utils" +import { cn } from "@/lib/utils"; import { DropdownMenu, DropdownMenuContent, @@ -19,8 +19,8 @@ import { DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, -} from "@/components/ui/dropdown-menu" -import { CheckIcon } from "lucide-react" +} from "@/components/ui/dropdown-menu"; +import { CheckIcon } from "lucide-react"; function Menubar({ className, ...props }: MenubarPrimitive.Props) { return ( @@ -28,27 +28,27 @@ function Menubar({ className, ...props }: MenubarPrimitive.Props) { data-slot="menubar" className={cn( "flex h-8 items-center gap-0.5 rounded-lg border p-[3px]", - className + className, )} {...props} /> - ) + ); } function MenubarMenu({ ...props }: React.ComponentProps) { - return + return ; } function MenubarGroup({ ...props }: React.ComponentProps) { - return + return ; } function MenubarPortal({ ...props }: React.ComponentProps) { - return + return ; } function MenubarTrigger({ @@ -60,11 +60,11 @@ function MenubarTrigger({ data-slot="menubar-trigger" className={cn( "flex items-center rounded-sm px-1.5 py-[2px] text-sm font-medium outline-hidden select-none hover:bg-muted aria-expanded:bg-muted", - className + className, )} {...props} /> - ) + ); } function MenubarContent({ @@ -80,10 +80,13 @@ function MenubarContent({ align={align} alignOffset={alignOffset} sideOffset={sideOffset} - className={cn("min-w-36 rounded-lg bg-popover p-1 text-popover-foreground shadow-md ring-1 ring-foreground/10 duration-100 data-[side=bottom]:slide-in-from-top-2 data-[side=inline-end]:slide-in-from-left-2 data-[side=inline-start]:slide-in-from-right-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 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95", className )} + className={cn( + "min-w-36 rounded-lg bg-popover p-1 text-popover-foreground shadow-md ring-1 ring-foreground/10 duration-100 data-[side=bottom]:slide-in-from-top-2 data-[side=inline-end]:slide-in-from-left-2 data-[side=inline-start]:slide-in-from-right-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 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95", + className, + )} {...props} /> - ) + ); } function MenubarItem({ @@ -99,11 +102,11 @@ function MenubarItem({ data-variant={variant} className={cn( "group/menubar-item gap-1.5 rounded-md px-1.5 py-1 text-sm focus:bg-accent focus:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground data-inset:pl-7 data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 data-[variant=destructive]:focus:text-destructive dark:data-[variant=destructive]:focus:bg-destructive/20 data-disabled:opacity-50 [&_svg:not([class*='size-'])]:size-4 data-[variant=destructive]:*:[svg]:text-destructive!", - className + className, )} {...props} /> - ) + ); } function MenubarCheckboxItem({ @@ -113,7 +116,7 @@ function MenubarCheckboxItem({ inset, ...props }: MenuPrimitive.CheckboxItem.Props & { - inset?: boolean + inset?: boolean; }) { return ( - + {children} - ) + ); } function MenubarRadioGroup({ ...props }: React.ComponentProps) { - return + return ; } function MenubarRadioItem({ @@ -149,7 +151,7 @@ function MenubarRadioItem({ inset, ...props }: MenuPrimitive.RadioItem.Props & { - inset?: boolean + inset?: boolean; }) { return ( - + {children} - ) + ); } function MenubarLabel({ @@ -177,7 +178,7 @@ function MenubarLabel({ inset, ...props }: React.ComponentProps & { - inset?: boolean + inset?: boolean; }) { return ( - ) + ); } function MenubarSeparator({ @@ -202,7 +203,7 @@ function MenubarSeparator({ className={cn("-mx-1 my-1 h-px bg-border", className)} {...props} /> - ) + ); } function MenubarShortcut({ @@ -214,17 +215,17 @@ function MenubarShortcut({ data-slot="menubar-shortcut" className={cn( "ml-auto text-xs tracking-widest text-muted-foreground group-focus/menubar-item:text-accent-foreground", - className + className, )} {...props} /> - ) + ); } function MenubarSub({ ...props }: React.ComponentProps) { - return + return ; } function MenubarSubTrigger({ @@ -232,7 +233,7 @@ function MenubarSubTrigger({ inset, ...props }: React.ComponentProps & { - inset?: boolean + inset?: boolean; }) { return ( - ) + ); } function MenubarSubContent({ @@ -254,10 +255,13 @@ function MenubarSubContent({ return ( - ) + ); } export { @@ -277,4 +281,4 @@ export { MenubarSub, MenubarSubTrigger, MenubarSubContent, -} +}; diff --git a/src/components/ui/message-scroller.tsx b/src/components/ui/message-scroller.tsx index be2fb5b..99963b9 100644 --- a/src/components/ui/message-scroller.tsx +++ b/src/components/ui/message-scroller.tsx @@ -1,21 +1,21 @@ -"use client" +"use client"; -import * as React from "react" +import * as React from "react"; import { MessageScroller as MessageScrollerPrimitive, useMessageScroller, useMessageScrollerScrollable, useMessageScrollerVisibility, -} from "@shadcn/react/message-scroller" +} from "@shadcn/react/message-scroller"; -import { cn } from "@/lib/utils" -import { Button } from "@/components/ui/button" -import { ArrowDownIcon } from "lucide-react" +import { cn } from "@/lib/utils"; +import { Button } from "@/components/ui/button"; +import { ArrowDownIcon } from "lucide-react"; function MessageScrollerProvider( - props: React.ComponentProps + props: React.ComponentProps, ) { - return + return ; } function MessageScroller({ @@ -27,11 +27,11 @@ function MessageScroller({ data-slot="message-scroller" className={cn( "group/message-scroller relative flex size-full min-h-0 flex-col overflow-hidden", - className + className, )} {...props} /> - ) + ); } function MessageScrollerViewport({ @@ -43,11 +43,11 @@ function MessageScrollerViewport({ data-slot="message-scroller-viewport" className={cn( "size-full min-h-0 min-w-0 scroll-fade-b scrollbar-thin scrollbar-gutter-stable overflow-y-auto overscroll-contain contain-content data-autoscrolling:scrollbar-thumb-transparent data-autoscrolling:scrollbar-track-transparent", - className + className, )} {...props} /> - ) + ); } function MessageScrollerContent({ @@ -60,7 +60,7 @@ function MessageScrollerContent({ className={cn("flex h-max min-h-full flex-col gap-6", className)} {...props} /> - ) + ); } function MessageScrollerItem({ @@ -74,11 +74,11 @@ function MessageScrollerItem({ scrollAnchor={scrollAnchor} className={cn( "min-w-0 shrink-0 [contain-intrinsic-size:auto_10rem] [content-visibility:auto]", - className + className, )} {...props} /> - ) + ); } function MessageScrollerButton({ @@ -100,22 +100,21 @@ function MessageScrollerButton({ direction={direction} className={cn( "absolute inset-s-1/2 -translate-x-1/2 border-border bg-background text-foreground transition-[translate,scale,opacity] duration-200 hover:bg-muted hover:text-foreground data-[active=false]:pointer-events-none data-[active=false]:scale-95 data-[active=false]:opacity-0 data-[active=false]:duration-400 data-[active=false]:ease-[cubic-bezier(0.7,0,0.84,0)] data-[active=true]:translate-y-0 data-[active=true]:scale-100 data-[active=true]:opacity-100 data-[active=true]:ease-[cubic-bezier(0.23,1,0.32,1)] data-[direction=end]:bottom-4 data-[direction=end]:data-[active=false]:translate-y-full data-[direction=start]:top-4 data-[direction=start]:data-[active=false]:-translate-y-full rtl:translate-x-1/2 data-[direction=start]:[&_svg]:rotate-180", - className + className, )} render={render ?? - ) + ); } function SidebarRail({ className, ...props }: React.ComponentProps<"button">) { - const { toggleSidebar } = useSidebar() + const { toggleSidebar } = useSidebar(); return (