Skip to content

Commit e560b08

Browse files
committed
chore: update version to 0.0.18 and add release date to package.json; refactor chart components for improved configuration handling and UI enhancements
1 parent ba3caa8 commit e560b08

File tree

8 files changed

+131
-43
lines changed

8 files changed

+131
-43
lines changed

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
{
22
"name": "duck-ui",
33
"private": true,
4-
"version": "0.0.17",
4+
"version": "0.0.18",
5+
"release_date": "2025-10-24",
56
"type": "module",
67
"scripts": {
78
"dev": "vite",

src/components/charts/ChartVisualizationPro.tsx

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ export const ChartVisualizationPro: React.FC<ChartVisualizationProProps> = ({
8282
yAxis: "",
8383
colors: DEFAULT_COLORS,
8484
showGrid: true,
85-
enableAnimations: true,
85+
enableAnimations: false,
8686
legend: { show: true, position: "top" },
8787
}
8888
);
@@ -121,7 +121,21 @@ export const ChartVisualizationPro: React.FC<ChartVisualizationProProps> = ({
121121
};
122122

123123
const applyConfig = () => {
124-
onConfigChange(localConfig);
124+
// Build series configuration from selected Y columns
125+
const series = selectedYColumns.map((col, idx) => ({
126+
column: col,
127+
label: col,
128+
color: DEFAULT_COLORS[idx % DEFAULT_COLORS.length],
129+
}));
130+
131+
// Update config with selected Y columns as series
132+
const updatedConfig = {
133+
...localConfig,
134+
series: series.length > 0 ? series : undefined,
135+
yAxis: series.length === 1 ? selectedYColumns[0] : undefined,
136+
};
137+
138+
onConfigChange(updatedConfig);
125139
toast.success("Chart configuration applied");
126140
};
127141

@@ -133,9 +147,10 @@ export const ChartVisualizationPro: React.FC<ChartVisualizationProProps> = ({
133147
yAxis: "",
134148
colors: DEFAULT_COLORS,
135149
showGrid: true,
136-
enableAnimations: true,
150+
enableAnimations: false,
137151
legend: { show: true, position: "top" },
138152
});
153+
setSelectedYColumns([]);
139154
toast.info("Chart cleared");
140155
};
141156

src/components/charts/CustomChartTooltip.tsx

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,12 @@ export const CustomChartTooltip: React.FC<CustomChartTooltipProps> = ({
3434

3535
return (
3636
<div
37-
className="rounded-lg border p-3 shadow-xl"
37+
className="rounded-lg border p-3 shadow-lg backdrop-blur-sm"
3838
style={{
3939
borderColor: 'hsl(var(--border))',
4040
backgroundColor: theme === 'dark'
41-
? 'hsl(222.2 84% 4.9%)' // Solid dark background
42-
: 'hsl(0 0% 100%)', // Solid white background
43-
opacity: 1,
41+
? 'rgba(9, 9, 11, 0.92)' // Semi-transparent dark
42+
: 'rgba(255, 255, 255, 0.92)', // Semi-transparent white
4443
}}
4544
>
4645
{label && (

src/components/explorer/ColumnNode.tsx

Lines changed: 94 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
import React, { useState } from "react";
2-
import { ChevronRight, ChevronDown, Hash, Type, Calendar, ToggleLeft } from "lucide-react";
2+
import {
3+
ChevronRight,
4+
ChevronDown,
5+
Hash,
6+
Type,
7+
Calendar,
8+
ToggleLeft,
9+
} from "lucide-react";
310
import { type ColumnStats } from "@/store";
411

512
interface ColumnNodeProps {
@@ -8,7 +15,12 @@ interface ColumnNodeProps {
815

916
const getTypeIcon = (type: string) => {
1017
const upperType = type.toUpperCase();
11-
if (upperType.includes("INT") || upperType.includes("DOUBLE") || upperType.includes("FLOAT") || upperType.includes("DECIMAL")) {
18+
if (
19+
upperType.includes("INT") ||
20+
upperType.includes("DOUBLE") ||
21+
upperType.includes("FLOAT") ||
22+
upperType.includes("DECIMAL")
23+
) {
1224
return <Hash className="w-3 h-3" />;
1325
} else if (upperType.includes("DATE") || upperType.includes("TIME")) {
1426
return <Calendar className="w-3 h-3" />;
@@ -20,7 +32,12 @@ const getTypeIcon = (type: string) => {
2032

2133
const getTypeColor = (type: string) => {
2234
const upperType = type.toUpperCase();
23-
if (upperType.includes("INT") || upperType.includes("DOUBLE") || upperType.includes("FLOAT") || upperType.includes("DECIMAL")) {
35+
if (
36+
upperType.includes("INT") ||
37+
upperType.includes("DOUBLE") ||
38+
upperType.includes("FLOAT") ||
39+
upperType.includes("DECIMAL")
40+
) {
2441
return "text-purple-500 bg-purple-500/10";
2542
} else if (upperType.includes("DATE") || upperType.includes("TIME")) {
2643
return "text-green-500 bg-green-500/10";
@@ -41,10 +58,10 @@ export const ColumnNode: React.FC<ColumnNodeProps> = ({ stats }) => {
4158

4259
// Safe parsing function that handles both string and number types
4360
const parseValue = (value: any): number => {
44-
if (typeof value === 'number') return value;
45-
if (typeof value === 'string') {
61+
if (typeof value === "number") return value;
62+
if (typeof value === "string") {
4663
// Remove quotes if present
47-
const cleaned = value.replace(/"/g, '');
64+
const cleaned = value.replace(/"/g, "");
4865
return parseFloat(cleaned) || 0;
4966
}
5067
return 0;
@@ -55,7 +72,8 @@ export const ColumnNode: React.FC<ColumnNodeProps> = ({ stats }) => {
5572
const uniqueCount = stats.approx_unique ? parseValue(stats.approx_unique) : 0;
5673
const totalCount = parseValue(stats.count);
5774

58-
const isNumeric = stats.column_type.toUpperCase().includes("INT") ||
75+
const isNumeric =
76+
stats.column_type.toUpperCase().includes("INT") ||
5977
stats.column_type.toUpperCase().includes("DOUBLE") ||
6078
stats.column_type.toUpperCase().includes("FLOAT") ||
6179
stats.column_type.toUpperCase().includes("DECIMAL");
@@ -73,13 +91,19 @@ export const ColumnNode: React.FC<ColumnNodeProps> = ({ stats }) => {
7391
<ChevronRight className="w-3 h-3 flex-shrink-0 text-muted-foreground" />
7492
)}
7593

76-
<div className={`flex-shrink-0 p-1 rounded ${getTypeColor(stats.column_type)}`}>
94+
<div
95+
className={`flex-shrink-0 p-1 rounded ${getTypeColor(
96+
stats.column_type
97+
)}`}
98+
>
7799
{getTypeIcon(stats.column_type)}
78100
</div>
79101

80102
<div className="flex-1 min-w-0">
81103
<div className="flex items-center gap-2">
82-
<span className="text-xs font-medium truncate">{stats.column_name}</span>
104+
<span className="text-xs font-medium truncate">
105+
{stats.column_name}
106+
</span>
83107
<span className="text-[10px] px-1.5 py-0.5 rounded bg-muted text-muted-foreground font-mono">
84108
{stats.column_type}
85109
</span>
@@ -91,7 +115,9 @@ export const ColumnNode: React.FC<ColumnNodeProps> = ({ stats }) => {
91115
<div className="flex items-center gap-1">
92116
<div className="flex-1 h-1.5 bg-muted rounded-full overflow-hidden">
93117
<div
94-
className={`h-full ${getFillColor(fillPercentage)} transition-all`}
118+
className={`h-full ${getFillColor(
119+
fillPercentage
120+
)} transition-all`}
95121
style={{ width: `${fillPercentage}%` }}
96122
/>
97123
</div>
@@ -119,7 +145,9 @@ export const ColumnNode: React.FC<ColumnNodeProps> = ({ stats }) => {
119145
</div>
120146
<div className="h-2 bg-background rounded-full overflow-hidden">
121147
<div
122-
className={`h-full ${getFillColor(fillPercentage)} transition-all`}
148+
className={`h-full ${getFillColor(
149+
fillPercentage
150+
)} transition-all`}
123151
style={{ width: `${fillPercentage}%` }}
124152
/>
125153
</div>
@@ -137,11 +165,18 @@ export const ColumnNode: React.FC<ColumnNodeProps> = ({ stats }) => {
137165
</div>
138166
<div className="flex justify-between">
139167
<span className="text-muted-foreground">Nulls:</span>
140-
<span className="font-mono">{((nullPercentage / 100) * totalCount).toFixed(0)}</span>
168+
<span className="font-mono">
169+
{((nullPercentage / 100) * totalCount).toFixed(0)}
170+
</span>
141171
</div>
142172
<div className="flex justify-between">
143173
<span className="text-muted-foreground">Cardinality:</span>
144-
<span className="font-mono">{((uniqueCount / totalCount) * 100).toFixed(1)}%</span>
174+
<span className="font-mono">
175+
{isNaN((uniqueCount / totalCount) * 100)
176+
? "0.0"
177+
: ((uniqueCount / totalCount) * 100).toFixed(1)}
178+
%
179+
</span>
145180
</div>
146181
</div>
147182

@@ -152,20 +187,32 @@ export const ColumnNode: React.FC<ColumnNodeProps> = ({ stats }) => {
152187
<div className="space-y-1 text-[10px]">
153188
<div className="flex justify-between">
154189
<span className="text-muted-foreground">Min:</span>
155-
<span className="font-mono">{parseValue(stats.min!).toLocaleString()}</span>
190+
<span className="font-mono">
191+
{parseValue(stats.min!).toLocaleString()}
192+
</span>
156193
</div>
157194
<div className="flex justify-between">
158195
<span className="text-muted-foreground">Max:</span>
159-
<span className="font-mono">{parseValue(stats.max!).toLocaleString()}</span>
196+
<span className="font-mono">
197+
{parseValue(stats.max!).toLocaleString()}
198+
</span>
160199
</div>
161200
<div className="flex justify-between">
162201
<span className="text-muted-foreground">Avg:</span>
163-
<span className="font-mono">{parseValue(stats.avg).toLocaleString(undefined, { maximumFractionDigits: 2 })}</span>
202+
<span className="font-mono">
203+
{parseValue(stats.avg).toLocaleString(undefined, {
204+
maximumFractionDigits: 2,
205+
})}
206+
</span>
164207
</div>
165208
{stats.std && (
166209
<div className="flex justify-between">
167210
<span className="text-muted-foreground">Std Dev:</span>
168-
<span className="font-mono">{parseValue(stats.std).toLocaleString(undefined, { maximumFractionDigits: 2 })}</span>
211+
<span className="font-mono">
212+
{parseValue(stats.std).toLocaleString(undefined, {
213+
maximumFractionDigits: 2,
214+
})}
215+
</span>
169216
</div>
170217
)}
171218
</div>
@@ -174,18 +221,26 @@ export const ColumnNode: React.FC<ColumnNodeProps> = ({ stats }) => {
174221
<>
175222
<div className="border-t border-border/50 my-1" />
176223
<div className="space-y-1 text-[10px]">
177-
<div className="text-[9px] text-muted-foreground font-medium mb-1">Quartiles</div>
224+
<div className="text-[9px] text-muted-foreground font-medium mb-1">
225+
Quartiles
226+
</div>
178227
<div className="flex justify-between">
179228
<span className="text-muted-foreground">Q1 (25%):</span>
180-
<span className="font-mono text-[9px]">{parseValue(stats.q25).toLocaleString()}</span>
229+
<span className="font-mono text-[9px]">
230+
{parseValue(stats.q25).toLocaleString()}
231+
</span>
181232
</div>
182233
<div className="flex justify-between">
183234
<span className="text-muted-foreground">Q2 (50%):</span>
184-
<span className="font-mono text-[9px]">{parseValue(stats.q50).toLocaleString()}</span>
235+
<span className="font-mono text-[9px]">
236+
{parseValue(stats.q50).toLocaleString()}
237+
</span>
185238
</div>
186239
<div className="flex justify-between">
187240
<span className="text-muted-foreground">Q3 (75%):</span>
188-
<span className="font-mono text-[9px]">{parseValue(stats.q75).toLocaleString()}</span>
241+
<span className="font-mono text-[9px]">
242+
{parseValue(stats.q75).toLocaleString()}
243+
</span>
189244
</div>
190245
</div>
191246
</>
@@ -199,12 +254,26 @@ export const ColumnNode: React.FC<ColumnNodeProps> = ({ stats }) => {
199254
<div className="border-t border-border/50 my-1" />
200255
<div className="space-y-1 text-[10px]">
201256
<div className="flex justify-between gap-2">
202-
<span className="text-muted-foreground flex-shrink-0">Min:</span>
203-
<span className="font-mono truncate text-right" title={stats.min}>{stats.min}</span>
257+
<span className="text-muted-foreground flex-shrink-0">
258+
Min:
259+
</span>
260+
<span
261+
className="font-mono truncate text-right"
262+
title={stats.min}
263+
>
264+
{stats.min}
265+
</span>
204266
</div>
205267
<div className="flex justify-between gap-2">
206-
<span className="text-muted-foreground flex-shrink-0">Max:</span>
207-
<span className="font-mono truncate text-right" title={stats.max}>{stats.max}</span>
268+
<span className="text-muted-foreground flex-shrink-0">
269+
Max:
270+
</span>
271+
<span
272+
className="font-mono truncate text-right"
273+
title={stats.max}
274+
>
275+
{stats.max}
276+
</span>
208277
</div>
209278
</div>
210279
</>

src/components/table/ColumnStatsPanel.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -120,8 +120,8 @@ const MiniChart: React.FC<{ stats: ColumnStats }> = ({ stats }) => {
120120
: ["#7c3aed", "#8b5cf6", "#a78bfa", "#c4b5fd", "#ddd6fe"];
121121

122122
return (
123-
<ResponsiveContainer width="100%" height={150}>
124-
<BarChart data={chartData} margin={{ top: 5, right: 5, bottom: 20, left: 5 }}>
123+
<ResponsiveContainer width="100%" height={250}>
124+
<BarChart data={chartData} margin={{ top: 15, right: 15, bottom: 20, left: 5 }}>
125125
<CartesianGrid strokeDasharray="3 3" opacity={0.3} />
126126
<XAxis
127127
dataKey="name"
@@ -137,6 +137,7 @@ const MiniChart: React.FC<{ stats: ColumnStats }> = ({ stats }) => {
137137
border: "1px solid #cbd5e1",
138138
borderRadius: "6px",
139139
fontSize: "12px",
140+
color: theme === "dark" ? "#65fc2eff" : "#0f172a",
140141
}}
141142
/>
142143
<Bar dataKey="value" radius={[4, 4, 0, 0]}>
@@ -259,7 +260,7 @@ export const ColumnStatsPanel: React.FC<ColumnStatsPanelProps> = ({
259260
}
260261

261262
return (
262-
<Card className="fixed bottom-4 left-4 z-30 w-[800px] max-h-[600px] shadow-lg border">
263+
<Card className="fixed bottom-4 left-4 z-30 w-7xl shadow-lg border">
263264
<CardHeader className="p-3 border-b">
264265
<div className="flex items-center justify-between">
265266
<div>

src/components/ui/multi-select.tsx

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -71,19 +71,19 @@ export function MultiSelect({
7171
aria-expanded={open}
7272
className={cn("w-full justify-between min-h-10 h-auto", className)}
7373
>
74-
<div className="flex gap-1 overflow-x-auto flex-1 mr-2 py-1 scrollbar-thin">
74+
<div className="flex gap-1 overflow-x-auto flex-1 mr-2 scrollbar-thin">
7575
{selectedOptions.length > 0 ? (
7676
selectedOptions.map((option) => (
7777
<Badge
7878
key={option.value}
79-
variant="secondary"
80-
className="shrink-0 gap-1.5 px-2.5 py-1"
79+
className="shrink-0 gap-1.5 font-medium"
8180
style={{
8281
backgroundColor: option.color
83-
? `${option.color}20`
82+
? `${option.color}65`
8483
: undefined,
8584
borderColor: option.color || undefined,
86-
borderWidth: '1px',
85+
borderWidth: '2px',
86+
boxShadow: option.color ? `0 1px 3px ${option.color}30` : undefined,
8787
}}
8888
>
8989
{option.color && (
@@ -92,7 +92,7 @@ export function MultiSelect({
9292
style={{ backgroundColor: option.color }}
9393
/>
9494
)}
95-
<span className="whitespace-nowrap">{option.label}</span>
95+
<span className="whitespace-nowrap text-foreground">{option.label}</span>
9696
<X
9797
className="h-3.5 w-3.5 cursor-pointer opacity-70 hover:opacity-100 shrink-0"
9898
onClick={(e) => handleRemove(option.value, e)}

src/components/workspace/HomeTab.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,8 @@ SELECT * FROM 'https://shell.duckdb.org/data/tpch/0_01/parquet/orders.parquet' L
122122

123123
//@ts-ignore
124124
const duck_ui_version = __DUCK_UI_VERSION__ || "Error loading version";
125+
//@ts-ignore
126+
const duck_ui_release_date = __DUCK_UI_RELEASE_DATE__ || "N/A";
125127

126128
const { theme } = useTheme();
127129

@@ -294,7 +296,7 @@ SELECT * FROM 'https://shell.duckdb.org/data/tpch/0_01/parquet/orders.parquet' L
294296
</TabsContent>
295297
</Tabs>
296298
<p className="text-muted-foreground text-center text-xs">
297-
Duck-UI Version: {duck_ui_version}
299+
Duck-UI Version: {duck_ui_version} - Released on: {duck_ui_release_date}
298300
</p>
299301
</div>
300302
</div>

vite.config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ export default defineConfig(({ mode }) => {
2222
},
2323
define: {
2424
__DUCK_UI_VERSION__: JSON.stringify(pkg.version),
25+
__DUCK_UI_RELEASE_DATE__: JSON.stringify(pkg.release_date),
2526
...processEnvValues // Spread the processed variables
2627
},
2728
};

0 commit comments

Comments
 (0)