Caleb Fahlgren commited on
Commit
6aaff3e
·
1 Parent(s): 08cd799

create custom pie chart and add other queries

Browse files
app/page.tsx CHANGED
@@ -1,12 +1,30 @@
1
  "use client"
2
 
 
 
 
 
 
 
 
 
 
 
3
  import { AreaChartStacked, ChartDataPoint } from "@/components/area-chart"
4
- import { useEffect, useState } from 'react'
5
- import * as duckdb from '@duckdb/duckdb-wasm'
6
 
7
  export default function IndexPage() {
8
- const [db, setDb] = useState<duckdb.AsyncDuckDB | null>(null)
9
  const [chartData, setChartData] = useState<ChartDataPoint[]>([])
 
 
 
 
 
 
 
 
 
10
 
11
  useEffect(() => {
12
  const initDB = async () => {
@@ -15,17 +33,19 @@ export default function IndexPage() {
15
  const JSDELIVR_BUNDLES = {
16
  mvp: {
17
  mainModule: `${CDN_BASE}/dist/duckdb-mvp.wasm`,
18
- mainWorker: `${CDN_BASE}/dist/duckdb-browser-mvp.worker.js`
19
  },
20
  eh: {
21
  mainModule: `${CDN_BASE}/dist/duckdb-eh.wasm`,
22
- mainWorker: `${CDN_BASE}/dist/duckdb-browser-eh.worker.js`
23
- }
24
  }
25
 
26
  const bundle = await duckdb.selectBundle(JSDELIVR_BUNDLES)
27
  const worker_url = URL.createObjectURL(
28
- new Blob([`importScripts("${bundle.mainWorker}");`], { type: 'text/javascript' })
 
 
29
  )
30
 
31
  const worker = new Worker(worker_url)
@@ -33,55 +53,67 @@ export default function IndexPage() {
33
  const db = new duckdb.AsyncDuckDB(logger, worker)
34
  await db.instantiate(bundle.mainModule)
35
 
36
- const conn = await db.connect()
37
 
38
- // create views from hf parquet files
39
- await conn.query(`
40
- CREATE VIEW models AS SELECT * FROM read_parquet('https://huggingface.co/datasets/cfahlgren1/hub-stats/resolve/refs%2Fconvert%2Fparquet/models/train/0000.parquet?download=true');
41
- CREATE VIEW datasets AS SELECT * FROM read_parquet('https://huggingface.co/datasets/cfahlgren1/hub-stats/resolve/refs%2Fconvert%2Fparquet/datasets/train/0000.parquet?download=true');
42
- CREATE VIEW spaces AS SELECT * FROM read_parquet('https://huggingface.co/datasets/cfahlgren1/hub-stats/resolve/refs%2Fconvert%2Fparquet/spaces/train/0000.parquet?download=true');
43
- `)
44
 
45
- setDb(db)
46
- await fetchChartData(db)
47
  }
48
 
49
  initDB()
 
 
 
 
 
 
 
50
  }, [])
51
 
52
- const fetchChartData = async (db: duckdb.AsyncDuckDB) => {
53
- const conn = await db.connect()
 
54
 
55
- const result = await conn.query(`
56
- WITH all_data AS (
57
- SELECT DATE_TRUNC('month', CAST(createdAt AS DATE)) AS month, 'model' AS type FROM models
58
- UNION ALL
59
- SELECT DATE_TRUNC('month', CAST(createdAt AS DATE)) AS month, 'dataset' AS type FROM datasets
60
- UNION ALL
61
- SELECT DATE_TRUNC('month', CAST(createdAt AS DATE)) AS month, 'space' AS type FROM spaces
62
- )
63
- SELECT
64
- month,
65
- COUNT(*) FILTER (WHERE type = 'model') AS models,
66
- COUNT(*) FILTER (WHERE type = 'dataset') AS datasets,
67
- COUNT(*) FILTER (WHERE type = 'space') AS spaces
68
- FROM all_data
69
- GROUP BY month
70
- ORDER BY month
71
- `)
72
-
73
- const data: ChartDataPoint[] = result.toArray().map(row => ({
74
  month: new Date(row.month),
75
  models: Number(row.models),
76
  datasets: Number(row.datasets),
77
- spaces: Number(row.spaces)
78
  }))
79
 
80
- console.log(data)
81
-
82
- await conn.close()
83
-
84
  setChartData(data)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
85
  }
86
 
87
  return (
@@ -92,8 +124,39 @@ export default function IndexPage() {
92
  </h1>
93
  </div>
94
  <div className="flex flex-col gap-4 max-w-6xl mt-10 w-full mx-auto">
95
- {chartData.length > 0 ? <AreaChartStacked data={chartData} /> : <p>Loading...</p>}
 
 
 
 
96
  </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
97
  </section>
98
  )
99
  }
 
1
  "use client"
2
 
3
+ import { useEffect, useState } from "react"
4
+ import * as duckdb from "@duckdb/duckdb-wasm"
5
+
6
+ import {
7
+ CREATE_VIEWS_QUERY,
8
+ FETCH_CHART_DATA_QUERY,
9
+ FETCH_DATASET_LICENSE_DATA_QUERY,
10
+ FETCH_MODEL_LICENSE_DATA_QUERY,
11
+ FETCH_SPACE_SDK_DATA_QUERY,
12
+ } from "@/lib/queries"
13
  import { AreaChartStacked, ChartDataPoint } from "@/components/area-chart"
14
+ import { CustomPieChart } from "@/components/pie-chart"
 
15
 
16
  export default function IndexPage() {
17
+ const [conn, setConn] = useState<duckdb.AsyncDuckDBConnection | null>(null)
18
  const [chartData, setChartData] = useState<ChartDataPoint[]>([])
19
+ const [modelLicenseData, setModelLicenseData] = useState<
20
+ Array<{ name: string; value: number; fill: string }>
21
+ >([])
22
+ const [datasetLicenseData, setDatasetLicenseData] = useState<
23
+ Array<{ name: string; value: number; fill: string }>
24
+ >([])
25
+ const [spaceSdkData, setSpaceSdkData] = useState<
26
+ Array<{ name: string; value: number; fill: string }>
27
+ >([])
28
 
29
  useEffect(() => {
30
  const initDB = async () => {
 
33
  const JSDELIVR_BUNDLES = {
34
  mvp: {
35
  mainModule: `${CDN_BASE}/dist/duckdb-mvp.wasm`,
36
+ mainWorker: `${CDN_BASE}/dist/duckdb-browser-mvp.worker.js`,
37
  },
38
  eh: {
39
  mainModule: `${CDN_BASE}/dist/duckdb-eh.wasm`,
40
+ mainWorker: `${CDN_BASE}/dist/duckdb-browser-eh.worker.js`,
41
+ },
42
  }
43
 
44
  const bundle = await duckdb.selectBundle(JSDELIVR_BUNDLES)
45
  const worker_url = URL.createObjectURL(
46
+ new Blob([`importScripts("${bundle.mainWorker}");`], {
47
+ type: "text/javascript",
48
+ })
49
  )
50
 
51
  const worker = new Worker(worker_url)
 
53
  const db = new duckdb.AsyncDuckDB(logger, worker)
54
  await db.instantiate(bundle.mainModule)
55
 
56
+ const connection = await db.connect()
57
 
58
+ await connection.query(CREATE_VIEWS_QUERY)
 
 
 
 
 
59
 
60
+ setConn(connection)
61
+ await fetchChartData(connection)
62
  }
63
 
64
  initDB()
65
+
66
+ // Clean up the connection when the component unmounts
67
+ return () => {
68
+ if (conn) {
69
+ conn.close()
70
+ }
71
+ }
72
  }, [])
73
 
74
+ const fetchChartData = async (connection: duckdb.AsyncDuckDBConnection) => {
75
+ // Use the imported query
76
+ const result = await connection.query(FETCH_CHART_DATA_QUERY)
77
 
78
+ const data: ChartDataPoint[] = result.toArray().map((row) => ({
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
79
  month: new Date(row.month),
80
  models: Number(row.models),
81
  datasets: Number(row.datasets),
82
+ spaces: Number(row.spaces),
83
  }))
84
 
 
 
 
 
85
  setChartData(data)
86
+
87
+ const [modelLicenseResult, datasetLicenseResult, spaceSdkResult] =
88
+ await Promise.all([
89
+ connection.query(FETCH_MODEL_LICENSE_DATA_QUERY),
90
+ connection.query(FETCH_DATASET_LICENSE_DATA_QUERY),
91
+ connection.query(FETCH_SPACE_SDK_DATA_QUERY),
92
+ ])
93
+
94
+ setModelLicenseData(
95
+ modelLicenseResult.toArray().map((row, index) => ({
96
+ name: row.tag.replace("license:", ""),
97
+ value: Number(row.count),
98
+ fill: `hsl(${index * 30}, 70%, 50%)`,
99
+ }))
100
+ )
101
+
102
+ setDatasetLicenseData(
103
+ datasetLicenseResult.toArray().map((row, index) => ({
104
+ name: row.tag.replace("license:", ""),
105
+ value: Number(row.count),
106
+ fill: `hsl(${index * 30}, 70%, 50%)`,
107
+ }))
108
+ )
109
+
110
+ setSpaceSdkData(
111
+ spaceSdkResult.toArray().map((row, index) => ({
112
+ name: row.sdk,
113
+ value: Number(row.count),
114
+ fill: `hsl(${index * 30}, 70%, 50%)`,
115
+ }))
116
+ )
117
  }
118
 
119
  return (
 
124
  </h1>
125
  </div>
126
  <div className="flex flex-col gap-4 max-w-6xl mt-10 w-full mx-auto">
127
+ {chartData.length > 0 ? (
128
+ <AreaChartStacked data={chartData} />
129
+ ) : (
130
+ <p>Loading...</p>
131
+ )}
132
  </div>
133
+ {modelLicenseData.length > 0 &&
134
+ datasetLicenseData.length > 0 &&
135
+ spaceSdkData.length > 0 && (
136
+ <div className="flex flex-wrap gap-8 max-w-6xl mt-10 w-full mx-auto">
137
+ <div className="flex-1 min-w-[300px]">
138
+ <CustomPieChart
139
+ title="Model Licenses"
140
+ data={modelLicenseData}
141
+ dataKey="value"
142
+ />
143
+ </div>
144
+ <div className="flex-1 min-w-[300px]">
145
+ <CustomPieChart
146
+ title="Dataset Licenses"
147
+ data={datasetLicenseData}
148
+ dataKey="value"
149
+ />
150
+ </div>
151
+ <div className="flex-1 min-w-[300px]">
152
+ <CustomPieChart
153
+ title="Space SDKs"
154
+ data={spaceSdkData}
155
+ dataKey="value"
156
+ />
157
+ </div>
158
+ </div>
159
+ )}
160
  </section>
161
  )
162
  }
components/area-chart.tsx CHANGED
@@ -19,39 +19,43 @@ import {
19
  } from "@/components/ui/chart"
20
 
21
  export interface ChartDataPoint {
22
- month: Date;
23
- models: number;
24
- datasets: number;
25
- spaces: number;
26
  }
27
 
28
  interface AreaChartStackedProps {
29
- data: ChartDataPoint[];
30
  }
31
 
32
  const chartConfig = {
33
  models: {
34
  label: "Models",
35
- color: "hsl(0, 70%, 70%)", // Light red
36
  },
37
  datasets: {
38
  label: "Datasets",
39
- color: "hsl(120, 70%, 40%)", // Darker green
40
  },
41
  spaces: {
42
  label: "Spaces",
43
- color: "hsl(210, 70%, 70%)", // Light blue
44
  },
45
  } satisfies ChartConfig
46
 
47
  export function AreaChartStacked({ data }: AreaChartStackedProps) {
48
- const sortedData = [...data].sort((a, b) => a.month.getTime() - b.month.getTime());
 
 
49
 
50
  return (
51
- <Card>
52
  <CardHeader>
53
- <CardTitle>Hugging Face Hub Growth</CardTitle>
54
- <CardDescription>
 
 
55
  Monthly creation trends for models, datasets, and spaces
56
  </CardDescription>
57
  </CardHeader>
@@ -72,44 +76,44 @@ export function AreaChartStacked({ data }: AreaChartStackedProps) {
72
  axisLine={false}
73
  tickMargin={8}
74
  tickFormatter={(value) => {
75
- const date = new Date(value);
76
- return date.toLocaleString('default', { month: 'short', year: 'numeric' });
 
 
 
77
  }}
78
  />
79
  <ChartTooltip
80
  cursor={true}
81
- content={
82
- <ChartTooltipContent
83
- indicator="line"
84
- hideLabel
85
- />
86
- }
87
  />
88
  <Area
89
  dataKey="spaces"
90
  type="natural"
91
- fill="hsl(210, 70%, 70%)"
92
  fillOpacity={0.4}
93
- stroke="hsl(210, 70%, 70%)"
94
  stackId="a"
95
  />
96
  <Area
97
  dataKey="datasets"
98
  type="natural"
99
- fill="hsl(120, 70%, 40%)"
100
  fillOpacity={0.2}
101
- stroke="hsl(120, 70%, 40%)"
102
  stackId="a"
103
  />
104
  <Area
105
  dataKey="models"
106
  type="natural"
107
- fill="hsl(0, 70%, 70%)"
108
  fillOpacity={0.4}
109
- stroke="hsl(0, 70%, 70%)"
110
  stackId="a"
111
  />
112
- <ChartLegend content={<ChartLegendContent />} />
 
 
113
  </AreaChart>
114
  </ChartContainer>
115
  </CardContent>
 
19
  } from "@/components/ui/chart"
20
 
21
  export interface ChartDataPoint {
22
+ month: Date
23
+ models: number
24
+ datasets: number
25
+ spaces: number
26
  }
27
 
28
  interface AreaChartStackedProps {
29
+ data: ChartDataPoint[]
30
  }
31
 
32
  const chartConfig = {
33
  models: {
34
  label: "Models",
35
+ color: "hsl(var(--chart-1))",
36
  },
37
  datasets: {
38
  label: "Datasets",
39
+ color: "hsl(var(--chart-2))",
40
  },
41
  spaces: {
42
  label: "Spaces",
43
+ color: "hsl(var(--chart-3))",
44
  },
45
  } satisfies ChartConfig
46
 
47
  export function AreaChartStacked({ data }: AreaChartStackedProps) {
48
+ const sortedData = [...data].sort(
49
+ (a, b) => a.month.getTime() - b.month.getTime()
50
+ )
51
 
52
  return (
53
+ <Card className="bg-[var(--card-background)]">
54
  <CardHeader>
55
+ <CardTitle className="text-[var(--card-text)]">
56
+ Hugging Face Hub Growth Each Month
57
+ </CardTitle>
58
+ <CardDescription className="text-[var(--card-text)]">
59
  Monthly creation trends for models, datasets, and spaces
60
  </CardDescription>
61
  </CardHeader>
 
76
  axisLine={false}
77
  tickMargin={8}
78
  tickFormatter={(value) => {
79
+ const date = new Date(value)
80
+ return date.toLocaleString("default", {
81
+ month: "short",
82
+ year: "numeric",
83
+ })
84
  }}
85
  />
86
  <ChartTooltip
87
  cursor={true}
88
+ content={<ChartTooltipContent indicator="line" hideLabel />}
 
 
 
 
 
89
  />
90
  <Area
91
  dataKey="spaces"
92
  type="natural"
93
+ fill="hsl(var(--chart-3))"
94
  fillOpacity={0.4}
95
+ stroke="hsl(var(--chart-3))"
96
  stackId="a"
97
  />
98
  <Area
99
  dataKey="datasets"
100
  type="natural"
101
+ fill="hsl(var(--chart-2))"
102
  fillOpacity={0.2}
103
+ stroke="hsl(var(--chart-2))"
104
  stackId="a"
105
  />
106
  <Area
107
  dataKey="models"
108
  type="natural"
109
+ fill="hsl(var(--chart-1))"
110
  fillOpacity={0.4}
111
+ stroke="hsl(var(--chart-1))"
112
  stackId="a"
113
  />
114
+ <ChartLegend
115
+ content={<ChartLegendContent className="text-white" />}
116
+ />
117
  </AreaChart>
118
  </ChartContainer>
119
  </CardContent>
components/pie-chart.tsx ADDED
@@ -0,0 +1,105 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ "use client"
2
+
3
+ import { Cell, LabelList, Pie, PieChart } from "recharts"
4
+
5
+ import {
6
+ Card,
7
+ CardContent,
8
+ CardDescription,
9
+ CardFooter,
10
+ CardHeader,
11
+ CardTitle,
12
+ } from "@/components/ui/card"
13
+ import {
14
+ ChartConfig,
15
+ ChartContainer,
16
+ ChartTooltip,
17
+ ChartTooltipContent,
18
+ } from "@/components/ui/chart"
19
+
20
+ interface PieChartProps {
21
+ title: string
22
+ description?: string
23
+ data: Array<{ name: string; value: number; fill: string }>
24
+ dataKey: string
25
+ }
26
+
27
+ const chartConfig: ChartConfig = {
28
+ value: {
29
+ label: "Value",
30
+ },
31
+ }
32
+
33
+ export function CustomPieChart({
34
+ title,
35
+ description,
36
+ data,
37
+ dataKey,
38
+ }: PieChartProps) {
39
+ const chartColors = [
40
+ "hsl(var(--chart-1))",
41
+ "hsl(var(--chart-2))",
42
+ "hsl(var(--chart-3))",
43
+ "hsl(var(--chart-4))",
44
+ "hsl(var(--chart-5))",
45
+ ]
46
+
47
+ // Sort data by value in descending order
48
+ const sortedData = [...data].sort((a, b) => b.value - a.value)
49
+
50
+ // Take top 4 items
51
+ const topItems = sortedData.slice(0, 4)
52
+
53
+ // Sum the rest under "Other"
54
+ const otherValue = sortedData
55
+ .slice(4)
56
+ .reduce((sum, item) => sum + item.value, 0)
57
+
58
+ const chartData =
59
+ otherValue > 0
60
+ ? [
61
+ ...topItems,
62
+ { name: "Other", value: otherValue, fill: chartColors[4] },
63
+ ]
64
+ : topItems
65
+
66
+ return (
67
+ <Card className="bg-[var(--card-background)]">
68
+ <CardHeader className="items-center pb-0">
69
+ <CardTitle className="text-[var(--card-text)]">{title}</CardTitle>
70
+ {description && ( // Conditionally render CardDescription
71
+ <CardDescription className="text-[var(--card-text)]">
72
+ {description}
73
+ </CardDescription>
74
+ )}
75
+ </CardHeader>
76
+ <CardContent className="flex-1 pb-0">
77
+ <ChartContainer
78
+ config={chartConfig}
79
+ className="mx-auto aspect-square max-h-[500px]"
80
+ >
81
+ <PieChart>
82
+ <ChartTooltip
83
+ cursor={false}
84
+ content={<ChartTooltipContent hideIndicator hideLabel />}
85
+ />
86
+ <Pie data={chartData} dataKey={dataKey} nameKey="name">
87
+ {chartData.map((entry, index) => (
88
+ <Cell
89
+ key={`cell-${index}`}
90
+ fill={chartColors[index % chartColors.length]}
91
+ />
92
+ ))}
93
+ <LabelList
94
+ dataKey="name"
95
+ className="fill-background"
96
+ stroke="none"
97
+ fontSize={12}
98
+ />
99
+ </Pie>
100
+ </PieChart>
101
+ </ChartContainer>
102
+ </CardContent>
103
+ </Card>
104
+ )
105
+ }
config/site.ts CHANGED
@@ -2,8 +2,7 @@ export type SiteConfig = typeof siteConfig
2
 
3
  export const siteConfig = {
4
  name: "Hugging Face Hub Stats",
5
- description:
6
- "Tracking Hugging Face Hub usage",
7
  mainNav: [
8
  {
9
  title: "Home",
 
2
 
3
  export const siteConfig = {
4
  name: "Hugging Face Hub Stats",
5
+ description: "Tracking Hugging Face Hub usage",
 
6
  mainNav: [
7
  {
8
  title: "Home",
lib/queries.ts ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ export const CREATE_VIEWS_QUERY = `
2
+ CREATE VIEW models AS SELECT * FROM read_parquet('https://huggingface.co/datasets/cfahlgren1/hub-stats/resolve/refs%2Fconvert%2Fparquet/models/train/0000.parquet?download=true');
3
+ CREATE VIEW datasets AS SELECT * FROM read_parquet('https://huggingface.co/datasets/cfahlgren1/hub-stats/resolve/refs%2Fconvert%2Fparquet/datasets/train/0000.parquet?download=true');
4
+ CREATE VIEW spaces AS SELECT * FROM read_parquet('https://huggingface.co/datasets/cfahlgren1/hub-stats/resolve/refs%2Fconvert%2Fparquet/spaces/train/0000.parquet?download=true');
5
+ `
6
+
7
+ export const FETCH_CHART_DATA_QUERY = `
8
+ WITH all_data AS (
9
+ SELECT DATE_TRUNC('month', CAST(createdAt AS DATE)) AS month, 'model' AS type FROM models
10
+ UNION ALL
11
+ SELECT DATE_TRUNC('month', CAST(createdAt AS DATE)) AS month, 'dataset' AS type FROM datasets
12
+ UNION ALL
13
+ SELECT DATE_TRUNC('month', CAST(createdAt AS DATE)) AS month, 'space' AS type FROM spaces
14
+ )
15
+ SELECT
16
+ month,
17
+ COUNT(*) FILTER (WHERE type = 'model') AS models,
18
+ COUNT(*) FILTER (WHERE type = 'dataset') AS datasets,
19
+ COUNT(*) FILTER (WHERE type = 'space') AS spaces
20
+ FROM all_data
21
+ GROUP BY month
22
+ ORDER BY month
23
+ `
24
+
25
+ export const FETCH_MODEL_LICENSE_DATA_QUERY = `
26
+ SELECT tag, COUNT(*) as count
27
+ FROM models, UNNEST(tags) AS t(tag)
28
+ WHERE tag LIKE 'license:%'
29
+ GROUP BY tag;
30
+ `
31
+
32
+ export const FETCH_DATASET_LICENSE_DATA_QUERY = `
33
+ SELECT tag, COUNT(*) as count
34
+ FROM datasets, UNNEST(tags) AS t(tag)
35
+ WHERE tag LIKE 'license:%'
36
+ GROUP BY tag;
37
+ `
38
+
39
+ export const FETCH_SPACE_SDK_DATA_QUERY = `
40
+ SELECT sdk, COUNT(*) as count
41
+ FROM spaces
42
+ GROUP BY sdk;
43
+ `
styles/globals.css CHANGED
@@ -4,62 +4,64 @@
4
 
5
  @layer base {
6
  :root {
7
- --background: 0 0% 100%;
8
- --foreground: 240 10% 3.9%;
9
- --card: 0 0% 100%;
10
- --card-foreground: 240 10% 3.9%;
11
- --popover: 0 0% 100%;
12
- --popover-foreground: 240 10% 3.9%;
13
- --primary: 240 5.9% 10%;
14
- --primary-foreground: 0 0% 98%;
15
- --secondary: 240 4.8% 95.9%;
16
- --secondary-foreground: 240 5.9% 10%;
17
- --muted: 240 4.8% 95.9%;
18
- --muted-foreground: 240 3.8% 46.1%;
19
- --accent: 240 4.8% 95.9%;
20
- --accent-foreground: 240 5.9% 10%;
21
- --destructive: 0 84.2% 60.2%;
22
  --destructive-foreground: 0 0% 98%;
23
- --border: 240 5.9% 90%;
24
- --input: 240 5.9% 90%;
25
- --ring: 240 10% 3.9%;
26
- --chart-1: 12 76% 61%;
27
- --chart-2: 173 58% 39%;
28
- --chart-3: 197 37% 24%;
29
- --chart-4: 43 74% 66%;
30
- --chart-5: 27 87% 67%;
 
 
 
 
 
 
 
 
31
  }
32
 
33
  .dark {
34
- --background: 240 10% 3.9%;
35
- --foreground: 0 0% 98%;
36
- --card: 240 10% 3.9%;
37
- --card-foreground: 0 0% 98%;
38
- --popover: 240 10% 3.9%;
39
- --popover-foreground: 0 0% 98%;
40
- --primary: 0 0% 98%;
41
- --primary-foreground: 240 5.9% 10%;
42
- --secondary: 240 3.7% 15.9%;
43
- --secondary-foreground: 0 0% 98%;
44
- --muted: 240 3.7% 15.9%;
45
- --muted-foreground: 240 5% 64.9%;
46
- --accent: 240 3.7% 15.9%;
47
- --accent-foreground: 0 0% 98%;
48
- --destructive: 0 62.8% 30.6%;
49
  --destructive-foreground: 0 0% 98%;
50
- --border: 240 3.7% 15.9%;
51
- --input: 240 3.7% 15.9%;
52
- --ring: 240 4.9% 83.9%;
53
- --chart-1: 220 70% 50%;
54
- --chart-2: 160 60% 45%;
55
- --chart-3: 30 80% 55%;
56
- --chart-4: 280 65% 60%;
57
- --chart-5: 340 75% 55%;
 
 
 
 
 
 
 
 
58
  }
59
  }
60
 
61
-
62
-
63
  @layer base {
64
  :root {
65
  --background: 0 0% 100%;
@@ -137,4 +139,4 @@
137
  @apply bg-background text-foreground;
138
  font-feature-settings: "rlig" 1, "calt" 1;
139
  }
140
- }
 
4
 
5
  @layer base {
6
  :root {
7
+ --background: 240 5% 6%;
8
+ --foreground: 60 5% 90%;
9
+ --primary: 240 0% 90%;
10
+ --primary-foreground: 60 0% 0%;
11
+ --secondary: 240 4% 15%;
12
+ --secondary-foreground: 60 5% 85%;
13
+ --accent: 240 0% 13%;
14
+ --accent-foreground: 60 0% 100%;
15
+ --destructive: 0 60% 50%;
 
 
 
 
 
 
16
  --destructive-foreground: 0 0% 98%;
17
+ --muted: 240 5% 25%;
18
+ --muted-foreground: 60 5% 85%;
19
+ --card: 240 4% 10%;
20
+ --card-foreground: 60 5% 90%;
21
+ --card-background: #1e1e1e;
22
+ --card-text: #fff;
23
+ --popover: 240 5% 15%;
24
+ --popover-foreground: 60 5% 85%;
25
+ --border: 240 6% 20%;
26
+ --input: 240 6% 20%;
27
+ --ring: 240 5% 90%;
28
+ --chart-1: 359 2% 90%;
29
+ --chart-2: 240 1% 74%;
30
+ --chart-3: 240 1% 58%;
31
+ --chart-4: 240 1% 42%;
32
+ --chart-5: 240 2% 26%;
33
  }
34
 
35
  .dark {
36
+ --background: 240 5% 6%;
37
+ --foreground: 60 5% 90%;
38
+ --primary: 240 0% 90%;
39
+ --primary-foreground: 60 0% 0%;
40
+ --secondary: 240 4% 15%;
41
+ --secondary-foreground: 60 5% 85%;
42
+ --accent: 240 0% 13%;
43
+ --accent-foreground: 60 0% 100%;
44
+ --destructive: 0 60% 50%;
 
 
 
 
 
 
45
  --destructive-foreground: 0 0% 98%;
46
+ --muted: 240 5% 25%;
47
+ --muted-foreground: 60 5% 85%;
48
+ --card-text: #fff;
49
+ --card: 240 4% 10%;
50
+ --card-foreground: 60 5% 90%;
51
+ --card-background: #1e1e1e;
52
+ --popover: 240 5% 15%;
53
+ --popover-foreground: 60 5% 85%;
54
+ --border: 240 6% 20%;
55
+ --input: 240 6% 20%;
56
+ --ring: 240 5% 90%;
57
+ --chart-1: 359 2% 90%;
58
+ --chart-2: 240 1% 74%;
59
+ --chart-3: 240 1% 58%;
60
+ --chart-4: 240 1% 42%;
61
+ --chart-5: 240 2% 26%;
62
  }
63
  }
64
 
 
 
65
  @layer base {
66
  :root {
67
  --background: 0 0% 100%;
 
139
  @apply bg-background text-foreground;
140
  font-feature-settings: "rlig" 1, "calt" 1;
141
  }
142
+ }