@databricks/appkit-ui 0.20.3 → 0.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"options.d.ts","names":[],"sources":["../../../src/react/charts/options.ts"],"mappings":";;;UAOiB,oBAAA;EACf,KAAA;EACA,QAAA,EAAU,MAAA;EACV,OAAA;EACA,MAAA;EACA,KAAA;EACA,UAAA;EACA,MAAA;AAAA;AAAA,UAGe,gBAAA,SAAyB,oBAAA;EACxC,SAAA,EAAW,SAAA;EACX,YAAA;EACA,OAAA;EACA,MAAA;EACA,UAAA;EACA,UAAA;AAAA;AAAA,iBAkBc,gBAAA,CACd,GAAA,EAAK,oBAAA,EACL,QAAA,aACC,MAAA;AAAA,iBAmCa,cAAA,CACd,GAAA,EAAK,oBAAA,EACL,SAAA,mBACA,WAAA,UACA,UAAA,WACA,aAAA,WACC,MAAA;AAAA,iBAyCa,wBAAA,CACd,GAAA,EAAK,oBAAA,EACL,OAAA,YACC,MAAA;AAAA,UAsCc,cAAA,SAAuB,oBAAA;EArJtC;EAuJA,SAAA;EAtJA;EAwJA,WAAA;EAtJA;EAwJA,GAAA;EAtJA;EAwJA,GAAA;EAxJU;EA0JV,UAAA;AAAA;AAAA,iBAGc,kBAAA,CACd,GAAA,EAAK,cAAA,GACJ,MAAA;AAAA,iBAsEa,oBAAA,CACd,GAAA,EAAK,gBAAA,GACJ,MAAA"}
1
+ {"version":3,"file":"options.d.ts","names":[],"sources":["../../../src/react/charts/options.ts"],"mappings":";;;UAOiB,oBAAA;EACf,KAAA;EACA,QAAA,EAAU,MAAA;EACV,OAAA;EACA,MAAA;EACA,KAAA;EACA,UAAA;EACA,MAAA;AAAA;AAAA,UAGe,gBAAA,SAAyB,oBAAA;EACxC,SAAA,EAAW,SAAA;EACX,YAAA;EACA,OAAA;EACA,MAAA;EACA,UAAA;EACA,UAAA;AAAA;AAAA,iBAkBc,gBAAA,CACd,GAAA,EAAK,oBAAA,EACL,QAAA,aACC,MAAA;AAAA,iBAmCa,cAAA,CACd,GAAA,EAAK,oBAAA,EACL,SAAA,mBACA,WAAA,UACA,UAAA,WACA,aAAA,WACC,MAAA;AAAA,iBA2Ca,wBAAA,CACd,GAAA,EAAK,oBAAA,EACL,OAAA,YACC,MAAA;AAAA,UAsCc,cAAA,SAAuB,oBAAA;EAvJtC;EAyJA,SAAA;EAxJA;EA0JA,WAAA;EAxJA;EA0JA,GAAA;EAxJA;EA0JA,GAAA;EA1JU;EA4JV,UAAA;AAAA;AAAA,iBAGc,kBAAA,CACd,GAAA,EAAK,cAAA,GACJ,MAAA;AAAA,iBAsEa,oBAAA,CACd,GAAA,EAAK,gBAAA,GACJ,MAAA"}
@@ -59,7 +59,9 @@ function buildPieOption(ctx, chartType, innerRadius, showLabels, labelPosition)
59
59
  label: {
60
60
  show: showLabels,
61
61
  position: labelPosition,
62
- formatter: "{b}: {d}%"
62
+ formatter: "{b}: {d}%",
63
+ color: "inherit",
64
+ textBorderWidth: 0
63
65
  },
64
66
  emphasis: { itemStyle: {
65
67
  shadowBlur: 10,
@@ -1 +1 @@
1
- {"version":3,"file":"options.js","names":[],"sources":["../../../src/react/charts/options.ts"],"sourcesContent":["import type { ChartType } from \"./types\";\nimport { createTimeSeriesData, formatLabel, truncateLabel } from \"./utils\";\n\n// ============================================================================\n// Option Builder Types\n// ============================================================================\n\nexport interface OptionBuilderContext {\n xData: (string | number)[];\n yDataMap: Record<string, (string | number)[]>;\n yFields: string[];\n colors: string[];\n title?: string;\n showLegend: boolean;\n xField?: string;\n}\n\nexport interface CartesianContext extends OptionBuilderContext {\n chartType: ChartType;\n isTimeSeries: boolean;\n stacked: boolean;\n smooth: boolean;\n showSymbol: boolean;\n symbolSize: number;\n}\n\n// ============================================================================\n// Base Option Builder\n// ============================================================================\n\nfunction buildBaseOption(ctx: OptionBuilderContext): Record<string, unknown> {\n return {\n title: ctx.title ? { text: ctx.title, left: \"center\" } : undefined,\n color: ctx.colors,\n };\n}\n\n// ============================================================================\n// Radar Chart Option\n// ============================================================================\n\nexport function buildRadarOption(\n ctx: OptionBuilderContext,\n showArea = true,\n): Record<string, unknown> {\n const maxValue = Math.max(\n ...ctx.yFields.flatMap((f) => ctx.yDataMap[f].map((v) => Number(v) || 0)),\n );\n\n return {\n ...buildBaseOption(ctx),\n tooltip: { trigger: \"item\" },\n legend:\n ctx.showLegend && ctx.yFields.length > 1 ? { top: \"bottom\" } : undefined,\n radar: {\n indicator: ctx.xData.map((name) => ({\n name: String(name),\n max: maxValue * 1.2,\n })),\n shape: \"polygon\",\n },\n series: [\n {\n type: \"radar\",\n data: ctx.yFields.map((key, idx) => ({\n name: formatLabel(key),\n value: ctx.yDataMap[key],\n itemStyle: { color: ctx.colors[idx % ctx.colors.length] },\n areaStyle: showArea ? { opacity: 0.3 } : undefined,\n })),\n },\n ],\n };\n}\n\n// ============================================================================\n// Pie/Donut Chart Option\n// ============================================================================\n\nexport function buildPieOption(\n ctx: OptionBuilderContext,\n chartType: \"pie\" | \"donut\",\n innerRadius: number,\n showLabels: boolean,\n labelPosition: string,\n): Record<string, unknown> {\n const pieData = ctx.xData.map((name, i) => ({\n name: String(name),\n value: ctx.yDataMap[ctx.yFields[0]]?.[i] ?? 0,\n }));\n\n const isDonut = chartType === \"donut\" || innerRadius > 0;\n\n return {\n ...buildBaseOption(ctx),\n tooltip: { trigger: \"item\", formatter: \"{b}: {c} ({d}%)\" },\n legend: ctx.showLegend\n ? { orient: \"vertical\", left: \"left\", top: \"middle\" }\n : undefined,\n series: [\n {\n type: \"pie\",\n radius: isDonut ? [`${innerRadius || 40}%`, \"70%\"] : \"70%\",\n center: [\"60%\", \"50%\"],\n data: pieData,\n label: {\n show: showLabels,\n position: labelPosition,\n formatter: \"{b}: {d}%\",\n },\n emphasis: {\n itemStyle: {\n shadowBlur: 10,\n shadowOffsetX: 0,\n shadowColor: \"rgba(0, 0, 0, 0.5)\",\n },\n },\n },\n ],\n };\n}\n\n// ============================================================================\n// Horizontal Bar Chart Option\n// ============================================================================\n\nexport function buildHorizontalBarOption(\n ctx: OptionBuilderContext,\n stacked: boolean,\n): Record<string, unknown> {\n const hasMultipleSeries = ctx.yFields.length > 1;\n\n return {\n ...buildBaseOption(ctx),\n tooltip: { trigger: \"axis\", axisPointer: { type: \"shadow\" } },\n legend: ctx.showLegend && hasMultipleSeries ? { top: \"bottom\" } : undefined,\n grid: {\n left: \"20%\",\n right: \"10%\",\n top: ctx.title ? \"15%\" : \"5%\",\n bottom: ctx.showLegend && hasMultipleSeries ? \"15%\" : \"5%\",\n },\n xAxis: { type: \"value\" },\n yAxis: {\n type: \"category\",\n data: ctx.xData,\n axisLabel: {\n width: 100,\n overflow: \"truncate\",\n formatter: (value: string) => truncateLabel(String(value)),\n },\n },\n series: ctx.yFields.map((key, idx) => ({\n name: formatLabel(key),\n type: \"bar\",\n data: ctx.yDataMap[key],\n stack: stacked ? \"total\" : undefined,\n itemStyle: { borderRadius: [0, 4, 4, 0] },\n color: ctx.colors[idx % ctx.colors.length],\n })),\n };\n}\n\n// ============================================================================\n// Heatmap Chart Option\n// ============================================================================\n\nexport interface HeatmapContext extends OptionBuilderContext {\n /** Y-axis categories (rows) */\n yAxisData: (string | number)[];\n /** Heatmap data as [xIndex, yIndex, value] tuples */\n heatmapData: [number, number, number][];\n /** Min value for color scale */\n min: number;\n /** Max value for color scale */\n max: number;\n /** Show value labels on cells */\n showLabels: boolean;\n}\n\nexport function buildHeatmapOption(\n ctx: HeatmapContext,\n): Record<string, unknown> {\n return {\n ...buildBaseOption(ctx),\n tooltip: {\n trigger: \"item\",\n formatter: (params: { data: [number, number, number] }) => {\n const [xIdx, yIdx, value] = params.data;\n const xLabel = ctx.xData[xIdx] ?? xIdx;\n const yLabel = ctx.yAxisData[yIdx] ?? yIdx;\n return `${xLabel}, ${yLabel}: ${value}`;\n },\n },\n grid: {\n left: \"15%\",\n right: \"15%\",\n top: ctx.title ? \"15%\" : \"10%\",\n bottom: \"15%\",\n },\n xAxis: {\n type: \"category\",\n data: ctx.xData,\n splitArea: { show: true },\n axisLabel: {\n rotate: ctx.xData.length > 10 ? 45 : 0,\n formatter: (v: string) => truncateLabel(String(v), 10),\n },\n },\n yAxis: {\n type: \"category\",\n data: ctx.yAxisData,\n splitArea: { show: true },\n axisLabel: {\n formatter: (v: string) => truncateLabel(String(v), 12),\n },\n },\n visualMap: {\n min: ctx.min,\n max: ctx.max,\n calculable: true,\n orient: \"vertical\",\n right: \"2%\",\n top: \"center\",\n inRange: {\n color: ctx.colors.length >= 2 ? ctx.colors : [\"#f0f0f0\", ctx.colors[0]],\n },\n },\n series: [\n {\n type: \"heatmap\",\n data: ctx.heatmapData,\n label: {\n show: ctx.showLabels,\n formatter: (params: { data: [number, number, number] }) =>\n String(params.data[2]),\n },\n emphasis: {\n itemStyle: {\n shadowBlur: 10,\n shadowColor: \"rgba(0, 0, 0, 0.5)\",\n },\n },\n },\n ],\n };\n}\n\n// ============================================================================\n// Cartesian Chart Option (line, bar, area, scatter)\n// ============================================================================\n\nexport function buildCartesianOption(\n ctx: CartesianContext,\n): Record<string, unknown> {\n const { chartType, isTimeSeries, stacked, smooth, showSymbol, symbolSize } =\n ctx;\n const hasMultipleSeries = ctx.yFields.length > 1;\n const seriesType = chartType === \"area\" ? \"line\" : chartType;\n const isScatter = chartType === \"scatter\";\n\n return {\n ...buildBaseOption(ctx),\n tooltip: { trigger: isScatter ? \"item\" : \"axis\" },\n legend: ctx.showLegend && hasMultipleSeries ? { top: \"bottom\" } : undefined,\n grid: {\n left: \"10%\",\n right: \"10%\",\n top: ctx.title ? \"15%\" : \"10%\",\n bottom: ctx.showLegend && hasMultipleSeries ? \"20%\" : \"15%\",\n },\n xAxis: {\n type: isScatter ? \"value\" : isTimeSeries ? \"time\" : \"category\",\n data: isScatter || isTimeSeries ? undefined : ctx.xData,\n name: ctx.xField ? formatLabel(ctx.xField) : undefined,\n axisLabel:\n isScatter || isTimeSeries\n ? { show: true }\n : {\n rotate: ctx.xData.length > 10 ? 45 : 0,\n formatter: (v: string) => truncateLabel(String(v), 10),\n },\n },\n yAxis: {\n type: \"value\",\n name: ctx.yFields.length === 1 ? formatLabel(ctx.yFields[0]) : undefined,\n },\n series: ctx.yFields.map((key, idx) => ({\n name: formatLabel(key),\n type: seriesType,\n data: isScatter\n ? ctx.xData.map((x, i) => [x, ctx.yDataMap[key][i]])\n : isTimeSeries\n ? createTimeSeriesData(ctx.xData, ctx.yDataMap[key])\n : ctx.yDataMap[key],\n smooth: chartType === \"line\" || chartType === \"area\" ? smooth : undefined,\n showSymbol:\n chartType === \"line\" || chartType === \"area\" ? showSymbol : undefined,\n symbol: isScatter ? \"circle\" : undefined,\n symbolSize: isScatter ? symbolSize : undefined,\n areaStyle: chartType === \"area\" ? { opacity: 0.3 } : undefined,\n stack: stacked && chartType === \"area\" ? \"total\" : undefined,\n itemStyle:\n chartType === \"bar\" ? { borderRadius: [4, 4, 0, 0] } : undefined,\n color: ctx.colors[idx % ctx.colors.length],\n })),\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"options.js","names":[],"sources":["../../../src/react/charts/options.ts"],"sourcesContent":["import type { ChartType } from \"./types\";\nimport { createTimeSeriesData, formatLabel, truncateLabel } from \"./utils\";\n\n// ============================================================================\n// Option Builder Types\n// ============================================================================\n\nexport interface OptionBuilderContext {\n xData: (string | number)[];\n yDataMap: Record<string, (string | number)[]>;\n yFields: string[];\n colors: string[];\n title?: string;\n showLegend: boolean;\n xField?: string;\n}\n\nexport interface CartesianContext extends OptionBuilderContext {\n chartType: ChartType;\n isTimeSeries: boolean;\n stacked: boolean;\n smooth: boolean;\n showSymbol: boolean;\n symbolSize: number;\n}\n\n// ============================================================================\n// Base Option Builder\n// ============================================================================\n\nfunction buildBaseOption(ctx: OptionBuilderContext): Record<string, unknown> {\n return {\n title: ctx.title ? { text: ctx.title, left: \"center\" } : undefined,\n color: ctx.colors,\n };\n}\n\n// ============================================================================\n// Radar Chart Option\n// ============================================================================\n\nexport function buildRadarOption(\n ctx: OptionBuilderContext,\n showArea = true,\n): Record<string, unknown> {\n const maxValue = Math.max(\n ...ctx.yFields.flatMap((f) => ctx.yDataMap[f].map((v) => Number(v) || 0)),\n );\n\n return {\n ...buildBaseOption(ctx),\n tooltip: { trigger: \"item\" },\n legend:\n ctx.showLegend && ctx.yFields.length > 1 ? { top: \"bottom\" } : undefined,\n radar: {\n indicator: ctx.xData.map((name) => ({\n name: String(name),\n max: maxValue * 1.2,\n })),\n shape: \"polygon\",\n },\n series: [\n {\n type: \"radar\",\n data: ctx.yFields.map((key, idx) => ({\n name: formatLabel(key),\n value: ctx.yDataMap[key],\n itemStyle: { color: ctx.colors[idx % ctx.colors.length] },\n areaStyle: showArea ? { opacity: 0.3 } : undefined,\n })),\n },\n ],\n };\n}\n\n// ============================================================================\n// Pie/Donut Chart Option\n// ============================================================================\n\nexport function buildPieOption(\n ctx: OptionBuilderContext,\n chartType: \"pie\" | \"donut\",\n innerRadius: number,\n showLabels: boolean,\n labelPosition: string,\n): Record<string, unknown> {\n const pieData = ctx.xData.map((name, i) => ({\n name: String(name),\n value: ctx.yDataMap[ctx.yFields[0]]?.[i] ?? 0,\n }));\n\n const isDonut = chartType === \"donut\" || innerRadius > 0;\n\n return {\n ...buildBaseOption(ctx),\n tooltip: { trigger: \"item\", formatter: \"{b}: {c} ({d}%)\" },\n legend: ctx.showLegend\n ? { orient: \"vertical\", left: \"left\", top: \"middle\" }\n : undefined,\n series: [\n {\n type: \"pie\",\n radius: isDonut ? [`${innerRadius || 40}%`, \"70%\"] : \"70%\",\n center: [\"60%\", \"50%\"],\n data: pieData,\n label: {\n show: showLabels,\n position: labelPosition,\n formatter: \"{b}: {d}%\",\n color: \"inherit\",\n textBorderWidth: 0,\n },\n emphasis: {\n itemStyle: {\n shadowBlur: 10,\n shadowOffsetX: 0,\n shadowColor: \"rgba(0, 0, 0, 0.5)\",\n },\n },\n },\n ],\n };\n}\n\n// ============================================================================\n// Horizontal Bar Chart Option\n// ============================================================================\n\nexport function buildHorizontalBarOption(\n ctx: OptionBuilderContext,\n stacked: boolean,\n): Record<string, unknown> {\n const hasMultipleSeries = ctx.yFields.length > 1;\n\n return {\n ...buildBaseOption(ctx),\n tooltip: { trigger: \"axis\", axisPointer: { type: \"shadow\" } },\n legend: ctx.showLegend && hasMultipleSeries ? { top: \"bottom\" } : undefined,\n grid: {\n left: \"20%\",\n right: \"10%\",\n top: ctx.title ? \"15%\" : \"5%\",\n bottom: ctx.showLegend && hasMultipleSeries ? \"15%\" : \"5%\",\n },\n xAxis: { type: \"value\" },\n yAxis: {\n type: \"category\",\n data: ctx.xData,\n axisLabel: {\n width: 100,\n overflow: \"truncate\",\n formatter: (value: string) => truncateLabel(String(value)),\n },\n },\n series: ctx.yFields.map((key, idx) => ({\n name: formatLabel(key),\n type: \"bar\",\n data: ctx.yDataMap[key],\n stack: stacked ? \"total\" : undefined,\n itemStyle: { borderRadius: [0, 4, 4, 0] },\n color: ctx.colors[idx % ctx.colors.length],\n })),\n };\n}\n\n// ============================================================================\n// Heatmap Chart Option\n// ============================================================================\n\nexport interface HeatmapContext extends OptionBuilderContext {\n /** Y-axis categories (rows) */\n yAxisData: (string | number)[];\n /** Heatmap data as [xIndex, yIndex, value] tuples */\n heatmapData: [number, number, number][];\n /** Min value for color scale */\n min: number;\n /** Max value for color scale */\n max: number;\n /** Show value labels on cells */\n showLabels: boolean;\n}\n\nexport function buildHeatmapOption(\n ctx: HeatmapContext,\n): Record<string, unknown> {\n return {\n ...buildBaseOption(ctx),\n tooltip: {\n trigger: \"item\",\n formatter: (params: { data: [number, number, number] }) => {\n const [xIdx, yIdx, value] = params.data;\n const xLabel = ctx.xData[xIdx] ?? xIdx;\n const yLabel = ctx.yAxisData[yIdx] ?? yIdx;\n return `${xLabel}, ${yLabel}: ${value}`;\n },\n },\n grid: {\n left: \"15%\",\n right: \"15%\",\n top: ctx.title ? \"15%\" : \"10%\",\n bottom: \"15%\",\n },\n xAxis: {\n type: \"category\",\n data: ctx.xData,\n splitArea: { show: true },\n axisLabel: {\n rotate: ctx.xData.length > 10 ? 45 : 0,\n formatter: (v: string) => truncateLabel(String(v), 10),\n },\n },\n yAxis: {\n type: \"category\",\n data: ctx.yAxisData,\n splitArea: { show: true },\n axisLabel: {\n formatter: (v: string) => truncateLabel(String(v), 12),\n },\n },\n visualMap: {\n min: ctx.min,\n max: ctx.max,\n calculable: true,\n orient: \"vertical\",\n right: \"2%\",\n top: \"center\",\n inRange: {\n color: ctx.colors.length >= 2 ? ctx.colors : [\"#f0f0f0\", ctx.colors[0]],\n },\n },\n series: [\n {\n type: \"heatmap\",\n data: ctx.heatmapData,\n label: {\n show: ctx.showLabels,\n formatter: (params: { data: [number, number, number] }) =>\n String(params.data[2]),\n },\n emphasis: {\n itemStyle: {\n shadowBlur: 10,\n shadowColor: \"rgba(0, 0, 0, 0.5)\",\n },\n },\n },\n ],\n };\n}\n\n// ============================================================================\n// Cartesian Chart Option (line, bar, area, scatter)\n// ============================================================================\n\nexport function buildCartesianOption(\n ctx: CartesianContext,\n): Record<string, unknown> {\n const { chartType, isTimeSeries, stacked, smooth, showSymbol, symbolSize } =\n ctx;\n const hasMultipleSeries = ctx.yFields.length > 1;\n const seriesType = chartType === \"area\" ? \"line\" : chartType;\n const isScatter = chartType === \"scatter\";\n\n return {\n ...buildBaseOption(ctx),\n tooltip: { trigger: isScatter ? \"item\" : \"axis\" },\n legend: ctx.showLegend && hasMultipleSeries ? { top: \"bottom\" } : undefined,\n grid: {\n left: \"10%\",\n right: \"10%\",\n top: ctx.title ? \"15%\" : \"10%\",\n bottom: ctx.showLegend && hasMultipleSeries ? \"20%\" : \"15%\",\n },\n xAxis: {\n type: isScatter ? \"value\" : isTimeSeries ? \"time\" : \"category\",\n data: isScatter || isTimeSeries ? undefined : ctx.xData,\n name: ctx.xField ? formatLabel(ctx.xField) : undefined,\n axisLabel:\n isScatter || isTimeSeries\n ? { show: true }\n : {\n rotate: ctx.xData.length > 10 ? 45 : 0,\n formatter: (v: string) => truncateLabel(String(v), 10),\n },\n },\n yAxis: {\n type: \"value\",\n name: ctx.yFields.length === 1 ? formatLabel(ctx.yFields[0]) : undefined,\n },\n series: ctx.yFields.map((key, idx) => ({\n name: formatLabel(key),\n type: seriesType,\n data: isScatter\n ? ctx.xData.map((x, i) => [x, ctx.yDataMap[key][i]])\n : isTimeSeries\n ? createTimeSeriesData(ctx.xData, ctx.yDataMap[key])\n : ctx.yDataMap[key],\n smooth: chartType === \"line\" || chartType === \"area\" ? smooth : undefined,\n showSymbol:\n chartType === \"line\" || chartType === \"area\" ? showSymbol : undefined,\n symbol: isScatter ? \"circle\" : undefined,\n symbolSize: isScatter ? symbolSize : undefined,\n areaStyle: chartType === \"area\" ? { opacity: 0.3 } : undefined,\n stack: stacked && chartType === \"area\" ? \"total\" : undefined,\n itemStyle:\n chartType === \"bar\" ? { borderRadius: [4, 4, 0, 0] } : undefined,\n color: ctx.colors[idx % ctx.colors.length],\n })),\n };\n}\n"],"mappings":"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"}
@@ -12,6 +12,11 @@ interface ChartInference {
12
12
  * Returns `null` when the data is not suitable for charting.
13
13
  */
14
14
  declare function inferChartType(rows: Record<string, unknown>[], columns: GenieColumnMeta[]): ChartInference | null;
15
+ /**
16
+ * Return the chart types that are compatible with the given data shape.
17
+ * Used to populate the chart-type selector dropdown.
18
+ */
19
+ declare function getCompatibleChartTypes(rows: Record<string, unknown>[], columns: GenieColumnMeta[]): ChartType[];
15
20
  //#endregion
16
- export { ChartInference, inferChartType };
21
+ export { ChartInference, getCompatibleChartTypes, inferChartType };
17
22
  //# sourceMappingURL=genie-chart-inference.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"genie-chart-inference.d.ts","names":[],"sources":["../../../src/react/genie/genie-chart-inference.ts"],"mappings":";;;;UAqDiB,cAAA;EACf,SAAA,EAAW,SAAA;EACX,IAAA;EACA,IAAA;AAAA;;;;;iBA6Bc,cAAA,CACd,IAAA,EAAM,MAAA,qBACN,OAAA,EAAS,eAAA,KACR,cAAA"}
1
+ {"version":3,"file":"genie-chart-inference.d.ts","names":[],"sources":["../../../src/react/genie/genie-chart-inference.ts"],"mappings":";;;;UAqDiB,cAAA;EACf,SAAA,EAAW,SAAA;EACX,IAAA;EACA,IAAA;AAAA;;;;;iBAoDc,cAAA,CACd,IAAA,EAAM,MAAA,qBACN,OAAA,EAAS,eAAA,KACR,cAAA;;;;;iBAyEa,uBAAA,CACd,IAAA,EAAM,MAAA,qBACN,OAAA,EAAS,eAAA,KACR,SAAA"}
@@ -5,6 +5,18 @@ const INFERENCE_CONFIG = {
5
5
  barMaxCategories: 100,
6
6
  groupedBarMaxCategories: 50
7
7
  };
8
+ function classifyColumns(rows, columns) {
9
+ if (rows.length < INFERENCE_CONFIG.minRows || columns.length < 2) return null;
10
+ const dateCols = columns.filter((c) => c.category === "date");
11
+ const numericCols = columns.filter((c) => c.category === "numeric");
12
+ const stringCols = columns.filter((c) => c.category === "string");
13
+ if (numericCols.length === 0) return null;
14
+ return {
15
+ dateCols,
16
+ numericCols,
17
+ stringCols
18
+ };
19
+ }
8
20
  function countUnique(rows, key) {
9
21
  const seen = /* @__PURE__ */ new Set();
10
22
  for (const row of rows) seen.add(row[key]);
@@ -19,11 +31,9 @@ function hasNegativeValues(rows, key) {
19
31
  * Returns `null` when the data is not suitable for charting.
20
32
  */
21
33
  function inferChartType(rows, columns) {
22
- if (rows.length < INFERENCE_CONFIG.minRows || columns.length < 2) return null;
23
- const dateCols = columns.filter((c) => c.category === "date");
24
- const numericCols = columns.filter((c) => c.category === "numeric");
25
- const stringCols = columns.filter((c) => c.category === "string");
26
- if (numericCols.length === 0) return null;
34
+ const classified = classifyColumns(rows, columns);
35
+ if (!classified) return null;
36
+ const { dateCols, numericCols, stringCols } = classified;
27
37
  if (dateCols.length > 0 && numericCols.length >= 1) return {
28
38
  chartType: "line",
29
39
  xKey: dateCols[0].name,
@@ -69,7 +79,51 @@ function inferChartType(rows, columns) {
69
79
  };
70
80
  return null;
71
81
  }
82
+ /**
83
+ * Return the chart types that are compatible with the given data shape.
84
+ * Used to populate the chart-type selector dropdown.
85
+ */
86
+ function getCompatibleChartTypes(rows, columns) {
87
+ const classified = classifyColumns(rows, columns);
88
+ if (!classified) return [];
89
+ const { dateCols, numericCols, stringCols } = classified;
90
+ if (dateCols.length > 0 && numericCols.length >= 1) return [
91
+ "line",
92
+ "bar",
93
+ "area"
94
+ ];
95
+ if (stringCols.length > 0 && numericCols.length >= 1) {
96
+ const xKey = stringCols[0].name;
97
+ const uniqueCategories = countUnique(rows, xKey);
98
+ if (numericCols.length === 1) {
99
+ const yKey = numericCols[0].name;
100
+ if (uniqueCategories <= INFERENCE_CONFIG.pieMaxCategories && !hasNegativeValues(rows, yKey)) return [
101
+ "pie",
102
+ "donut",
103
+ "bar",
104
+ "line",
105
+ "area"
106
+ ];
107
+ return [
108
+ "bar",
109
+ "line",
110
+ "area"
111
+ ];
112
+ }
113
+ return [
114
+ "bar",
115
+ "line",
116
+ "area"
117
+ ];
118
+ }
119
+ if (numericCols.length >= 2 && stringCols.length === 0 && dateCols.length === 0) return [
120
+ "scatter",
121
+ "line",
122
+ "area"
123
+ ];
124
+ return [];
125
+ }
72
126
 
73
127
  //#endregion
74
- export { inferChartType };
128
+ export { getCompatibleChartTypes, inferChartType };
75
129
  //# sourceMappingURL=genie-chart-inference.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"genie-chart-inference.js","names":[],"sources":["../../../src/react/genie/genie-chart-inference.ts"],"sourcesContent":["/**\n * ┌─────────────────────────────────────────────────────────────────────┐\n * │ CHART INFERENCE RULES │\n * │ │\n * │ These rules determine what chart type is shown for Genie query │\n * │ results. Modify thresholds and chart type mappings here. │\n * │ │\n * │ Column types are classified from SQL type_name: │\n * │ DATE: DATE, TIMESTAMP, TIMESTAMP_NTZ │\n * │ NUMERIC: DECIMAL, INT, DOUBLE, FLOAT, LONG, etc. │\n * │ STRING: STRING, VARCHAR, CHAR │\n * │ │\n * │ Rules (applied in priority order): │\n * │ │\n * │ SKIP (return null): │\n * │ - < 2 rows │\n * │ - < 2 columns │\n * │ - No numeric columns │\n * │ │\n * │ MATCH: │\n * │ 1. DATE + numeric(s) → line (timeseries) │\n * │ 2. STRING + 1 numeric, ≤7 cats → pie │\n * │ 3. STRING + 1 numeric, ≤100 cats → bar │\n * │ 4. STRING + 1 numeric, >100 cats → line │\n * │ 5. STRING + N numerics, ≤50 cats → bar (grouped) │\n * │ 6. STRING + N numerics, >50 cats → line (multi-series) │\n * │ 7. 2+ numerics only → scatter │\n * │ 8. Otherwise → null (skip) │\n * │ │\n * │ KNOWN LIMITATIONS: │\n * │ - First-column heuristic: picks first string col as category │\n * │ - No semantic understanding (can't tell ID from meaningful val) │\n * └─────────────────────────────────────────────────────────────────────┘\n */\n\nimport type { ChartType } from \"../charts/types\";\nimport type { GenieColumnMeta } from \"./genie-query-transform\";\n\n// ---------------------------------------------------------------------------\n// Configuration — edit thresholds here\n// ---------------------------------------------------------------------------\n\nconst INFERENCE_CONFIG = {\n /** Min rows required to show any chart */\n minRows: 2,\n /** Max unique categories for pie chart */\n pieMaxCategories: 7,\n /** Max unique categories for bar chart (single series) */\n barMaxCategories: 100,\n /** Max unique categories for grouped bar chart (multi series) */\n groupedBarMaxCategories: 50,\n} as const;\n\nexport interface ChartInference {\n chartType: ChartType;\n xKey: string;\n yKey: string | string[];\n}\n\nfunction countUnique(rows: Record<string, unknown>[], key: string): number {\n const seen = new Set<unknown>();\n for (const row of rows) {\n seen.add(row[key]);\n }\n return seen.size;\n}\n\nfunction hasNegativeValues(\n rows: Record<string, unknown>[],\n key: string,\n): boolean {\n for (const row of rows) {\n if (Number(row[key]) < 0) return true;\n }\n return false;\n}\n\n// ---------------------------------------------------------------------------\n// Main inference function\n// ---------------------------------------------------------------------------\n\n/**\n * Infer the best chart type for the given Genie query result.\n * Returns `null` when the data is not suitable for charting.\n */\nexport function inferChartType(\n rows: Record<string, unknown>[],\n columns: GenieColumnMeta[],\n): ChartInference | null {\n // Guard: need at least minRows and 2 columns\n if (rows.length < INFERENCE_CONFIG.minRows || columns.length < 2) {\n return null;\n }\n\n const dateCols = columns.filter((c) => c.category === \"date\");\n const numericCols = columns.filter((c) => c.category === \"numeric\");\n const stringCols = columns.filter((c) => c.category === \"string\");\n\n // Guard: must have at least one numeric column\n if (numericCols.length === 0) return null;\n\n // Rule 1: DATE + numeric(s) → line (timeseries)\n if (dateCols.length > 0 && numericCols.length >= 1) {\n return {\n chartType: \"line\",\n xKey: dateCols[0].name,\n yKey:\n numericCols.length === 1\n ? numericCols[0].name\n : numericCols.map((c) => c.name),\n };\n }\n\n // Rules 2–6: STRING + numeric(s)\n if (stringCols.length > 0 && numericCols.length >= 1) {\n const xKey = stringCols[0].name;\n const uniqueCategories = countUnique(rows, xKey);\n\n if (numericCols.length === 1) {\n const yKey = numericCols[0].name;\n\n // Rule 2: few categories → pie (skip if negative values)\n if (\n uniqueCategories <= INFERENCE_CONFIG.pieMaxCategories &&\n !hasNegativeValues(rows, yKey)\n ) {\n return { chartType: \"pie\", xKey, yKey };\n }\n // Rule 3: moderate categories → bar\n if (uniqueCategories <= INFERENCE_CONFIG.barMaxCategories) {\n return { chartType: \"bar\", xKey, yKey };\n }\n // Rule 4: many categories → line\n return { chartType: \"line\", xKey, yKey };\n }\n\n // Multiple numerics\n const yKey = numericCols.map((c) => c.name);\n\n // Rule 5: moderate categories → bar (grouped)\n if (uniqueCategories <= INFERENCE_CONFIG.groupedBarMaxCategories) {\n return { chartType: \"bar\", xKey, yKey };\n }\n // Rule 6: many categories → line (multi-series)\n return { chartType: \"line\", xKey, yKey };\n }\n\n // Rule 7: 2+ numerics only (no string, no date) → scatter\n if (\n numericCols.length >= 2 &&\n stringCols.length === 0 &&\n dateCols.length === 0\n ) {\n return {\n chartType: \"scatter\",\n xKey: numericCols[0].name,\n yKey: numericCols[1].name,\n };\n }\n\n // Rule 8: fallback — no chart\n return null;\n}\n"],"mappings":";AA0CA,MAAM,mBAAmB;CAEvB,SAAS;CAET,kBAAkB;CAElB,kBAAkB;CAElB,yBAAyB;CAC1B;AAQD,SAAS,YAAY,MAAiC,KAAqB;CACzE,MAAM,uBAAO,IAAI,KAAc;AAC/B,MAAK,MAAM,OAAO,KAChB,MAAK,IAAI,IAAI,KAAK;AAEpB,QAAO,KAAK;;AAGd,SAAS,kBACP,MACA,KACS;AACT,MAAK,MAAM,OAAO,KAChB,KAAI,OAAO,IAAI,KAAK,GAAG,EAAG,QAAO;AAEnC,QAAO;;;;;;AAWT,SAAgB,eACd,MACA,SACuB;AAEvB,KAAI,KAAK,SAAS,iBAAiB,WAAW,QAAQ,SAAS,EAC7D,QAAO;CAGT,MAAM,WAAW,QAAQ,QAAQ,MAAM,EAAE,aAAa,OAAO;CAC7D,MAAM,cAAc,QAAQ,QAAQ,MAAM,EAAE,aAAa,UAAU;CACnE,MAAM,aAAa,QAAQ,QAAQ,MAAM,EAAE,aAAa,SAAS;AAGjE,KAAI,YAAY,WAAW,EAAG,QAAO;AAGrC,KAAI,SAAS,SAAS,KAAK,YAAY,UAAU,EAC/C,QAAO;EACL,WAAW;EACX,MAAM,SAAS,GAAG;EAClB,MACE,YAAY,WAAW,IACnB,YAAY,GAAG,OACf,YAAY,KAAK,MAAM,EAAE,KAAK;EACrC;AAIH,KAAI,WAAW,SAAS,KAAK,YAAY,UAAU,GAAG;EACpD,MAAM,OAAO,WAAW,GAAG;EAC3B,MAAM,mBAAmB,YAAY,MAAM,KAAK;AAEhD,MAAI,YAAY,WAAW,GAAG;GAC5B,MAAM,OAAO,YAAY,GAAG;AAG5B,OACE,oBAAoB,iBAAiB,oBACrC,CAAC,kBAAkB,MAAM,KAAK,CAE9B,QAAO;IAAE,WAAW;IAAO;IAAM;IAAM;AAGzC,OAAI,oBAAoB,iBAAiB,iBACvC,QAAO;IAAE,WAAW;IAAO;IAAM;IAAM;AAGzC,UAAO;IAAE,WAAW;IAAQ;IAAM;IAAM;;EAI1C,MAAM,OAAO,YAAY,KAAK,MAAM,EAAE,KAAK;AAG3C,MAAI,oBAAoB,iBAAiB,wBACvC,QAAO;GAAE,WAAW;GAAO;GAAM;GAAM;AAGzC,SAAO;GAAE,WAAW;GAAQ;GAAM;GAAM;;AAI1C,KACE,YAAY,UAAU,KACtB,WAAW,WAAW,KACtB,SAAS,WAAW,EAEpB,QAAO;EACL,WAAW;EACX,MAAM,YAAY,GAAG;EACrB,MAAM,YAAY,GAAG;EACtB;AAIH,QAAO"}
1
+ {"version":3,"file":"genie-chart-inference.js","names":[],"sources":["../../../src/react/genie/genie-chart-inference.ts"],"sourcesContent":["/**\n * ┌─────────────────────────────────────────────────────────────────────┐\n * │ CHART INFERENCE RULES │\n * │ │\n * │ These rules determine what chart type is shown for Genie query │\n * │ results. Modify thresholds and chart type mappings here. │\n * │ │\n * │ Column types are classified from SQL type_name: │\n * │ DATE: DATE, TIMESTAMP, TIMESTAMP_NTZ │\n * │ NUMERIC: DECIMAL, INT, DOUBLE, FLOAT, LONG, etc. │\n * │ STRING: STRING, VARCHAR, CHAR │\n * │ │\n * │ Rules (applied in priority order): │\n * │ │\n * │ SKIP (return null): │\n * │ - < 2 rows │\n * │ - < 2 columns │\n * │ - No numeric columns │\n * │ │\n * │ MATCH: │\n * │ 1. DATE + numeric(s) → line (timeseries) │\n * │ 2. STRING + 1 numeric, ≤7 cats → pie │\n * │ 3. STRING + 1 numeric, ≤100 cats → bar │\n * │ 4. STRING + 1 numeric, >100 cats → line │\n * │ 5. STRING + N numerics, ≤50 cats → bar (grouped) │\n * │ 6. STRING + N numerics, >50 cats → line (multi-series) │\n * │ 7. 2+ numerics only → scatter │\n * │ 8. Otherwise → null (skip) │\n * │ │\n * │ KNOWN LIMITATIONS: │\n * │ - First-column heuristic: picks first string col as category │\n * │ - No semantic understanding (can't tell ID from meaningful val) │\n * └─────────────────────────────────────────────────────────────────────┘\n */\n\nimport type { ChartType } from \"../charts/types\";\nimport type { GenieColumnMeta } from \"./genie-query-transform\";\n\n// ---------------------------------------------------------------------------\n// Configuration — edit thresholds here\n// ---------------------------------------------------------------------------\n\nconst INFERENCE_CONFIG = {\n /** Min rows required to show any chart */\n minRows: 2,\n /** Max unique categories for pie chart */\n pieMaxCategories: 7,\n /** Max unique categories for bar chart (single series) */\n barMaxCategories: 100,\n /** Max unique categories for grouped bar chart (multi series) */\n groupedBarMaxCategories: 50,\n} as const;\n\nexport interface ChartInference {\n chartType: ChartType;\n xKey: string;\n yKey: string | string[];\n}\n\ninterface ClassifiedColumns {\n dateCols: GenieColumnMeta[];\n numericCols: GenieColumnMeta[];\n stringCols: GenieColumnMeta[];\n}\n\nfunction classifyColumns(\n rows: Record<string, unknown>[],\n columns: GenieColumnMeta[],\n): ClassifiedColumns | null {\n if (rows.length < INFERENCE_CONFIG.minRows || columns.length < 2) {\n return null;\n }\n\n const dateCols = columns.filter((c) => c.category === \"date\");\n const numericCols = columns.filter((c) => c.category === \"numeric\");\n const stringCols = columns.filter((c) => c.category === \"string\");\n\n if (numericCols.length === 0) return null;\n\n return { dateCols, numericCols, stringCols };\n}\n\nfunction countUnique(rows: Record<string, unknown>[], key: string): number {\n const seen = new Set<unknown>();\n for (const row of rows) {\n seen.add(row[key]);\n }\n return seen.size;\n}\n\nfunction hasNegativeValues(\n rows: Record<string, unknown>[],\n key: string,\n): boolean {\n for (const row of rows) {\n if (Number(row[key]) < 0) return true;\n }\n return false;\n}\n\n// ---------------------------------------------------------------------------\n// Main inference function\n// ---------------------------------------------------------------------------\n\n/**\n * Infer the best chart type for the given Genie query result.\n * Returns `null` when the data is not suitable for charting.\n */\nexport function inferChartType(\n rows: Record<string, unknown>[],\n columns: GenieColumnMeta[],\n): ChartInference | null {\n const classified = classifyColumns(rows, columns);\n if (!classified) return null;\n\n const { dateCols, numericCols, stringCols } = classified;\n\n // Rule 1: DATE + numeric(s) → line (timeseries)\n if (dateCols.length > 0 && numericCols.length >= 1) {\n return {\n chartType: \"line\",\n xKey: dateCols[0].name,\n yKey:\n numericCols.length === 1\n ? numericCols[0].name\n : numericCols.map((c) => c.name),\n };\n }\n\n // Rules 2–6: STRING + numeric(s)\n if (stringCols.length > 0 && numericCols.length >= 1) {\n const xKey = stringCols[0].name;\n const uniqueCategories = countUnique(rows, xKey);\n\n if (numericCols.length === 1) {\n const yKey = numericCols[0].name;\n\n // Rule 2: few categories → pie (skip if negative values)\n if (\n uniqueCategories <= INFERENCE_CONFIG.pieMaxCategories &&\n !hasNegativeValues(rows, yKey)\n ) {\n return { chartType: \"pie\", xKey, yKey };\n }\n // Rule 3: moderate categories → bar\n if (uniqueCategories <= INFERENCE_CONFIG.barMaxCategories) {\n return { chartType: \"bar\", xKey, yKey };\n }\n // Rule 4: many categories → line\n return { chartType: \"line\", xKey, yKey };\n }\n\n // Multiple numerics\n const yKey = numericCols.map((c) => c.name);\n\n // Rule 5: moderate categories → bar (grouped)\n if (uniqueCategories <= INFERENCE_CONFIG.groupedBarMaxCategories) {\n return { chartType: \"bar\", xKey, yKey };\n }\n // Rule 6: many categories → line (multi-series)\n return { chartType: \"line\", xKey, yKey };\n }\n\n // Rule 7: 2+ numerics only (no string, no date) → scatter\n if (\n numericCols.length >= 2 &&\n stringCols.length === 0 &&\n dateCols.length === 0\n ) {\n return {\n chartType: \"scatter\",\n xKey: numericCols[0].name,\n yKey: numericCols[1].name,\n };\n }\n\n // Rule 8: fallback — no chart\n return null;\n}\n\n/**\n * Return the chart types that are compatible with the given data shape.\n * Used to populate the chart-type selector dropdown.\n */\nexport function getCompatibleChartTypes(\n rows: Record<string, unknown>[],\n columns: GenieColumnMeta[],\n): ChartType[] {\n const classified = classifyColumns(rows, columns);\n if (!classified) return [];\n\n const { dateCols, numericCols, stringCols } = classified;\n\n // DATE + numeric(s) → timeseries-compatible types\n if (dateCols.length > 0 && numericCols.length >= 1) {\n return [\"line\", \"bar\", \"area\"];\n }\n\n // STRING + numeric(s)\n if (stringCols.length > 0 && numericCols.length >= 1) {\n const xKey = stringCols[0].name;\n const uniqueCategories = countUnique(rows, xKey);\n\n if (numericCols.length === 1) {\n const yKey = numericCols[0].name;\n // Few categories and no negatives → pie/donut are viable\n if (\n uniqueCategories <= INFERENCE_CONFIG.pieMaxCategories &&\n !hasNegativeValues(rows, yKey)\n ) {\n return [\"pie\", \"donut\", \"bar\", \"line\", \"area\"];\n }\n return [\"bar\", \"line\", \"area\"];\n }\n\n // Multiple numerics\n return [\"bar\", \"line\", \"area\"];\n }\n\n // 2+ numerics only → scatter-compatible\n if (\n numericCols.length >= 2 &&\n stringCols.length === 0 &&\n dateCols.length === 0\n ) {\n return [\"scatter\", \"line\", \"area\"];\n }\n\n return [];\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"genie-query-visualization.d.ts","names":[],"sources":["../../../src/react/genie/genie-query-visualization.tsx"],"mappings":";;;;;UAmBU,4BAAA;;EAER,IAAA,EAAM,sBAAA;;EAEN,SAAA;AAAA;;;;;;;;iBAUc,uBAAA,CAAA;EACd,IAAA;EACA;AAAA,GACC,4BAAA,GAA4B,kBAAA,CAAA,GAAA,CAAA,OAAA"}
1
+ {"version":3,"file":"genie-query-visualization.d.ts","names":[],"sources":["../../../src/react/genie/genie-query-visualization.tsx"],"mappings":";;;;;UA4CU,4BAAA;;EAER,IAAA,EAAM,sBAAA;;EAEN,SAAA;AAAA;;;;;;;;iBAUc,uBAAA,CAAA;EACd,IAAA;EACA;AAAA,GACC,4BAAA,GAA4B,kBAAA,CAAA,GAAA,CAAA,OAAA"}
@@ -1,15 +1,28 @@
1
1
  import { BaseChart } from "../charts/base.js";
2
2
  import { ChartErrorBoundary } from "../charts/chart-error-boundary.js";
3
- import { inferChartType } from "./genie-chart-inference.js";
3
+ import { Button } from "../ui/button.js";
4
+ import { getCompatibleChartTypes, inferChartType } from "./genie-chart-inference.js";
5
+ import { DropdownMenu, DropdownMenuContent, DropdownMenuLabel, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuTrigger } from "../ui/dropdown-menu.js";
4
6
  import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "../ui/table.js";
5
7
  import { Tabs, TabsContent, TabsList, TabsTrigger } from "../ui/tabs.js";
6
8
  import { transformGenieData } from "./genie-query-transform.js";
7
- import { useMemo } from "react";
9
+ import { useMemo, useState } from "react";
8
10
  import { jsx, jsxs } from "react/jsx-runtime";
11
+ import { BarChart3Icon, ChevronDownIcon } from "lucide-react";
9
12
 
10
13
  //#region src/react/genie/genie-query-visualization.tsx
11
14
  const TABLE_ROW_LIMIT = 50;
12
15
  const CHART_HEIGHT = 250;
16
+ const CHART_TYPE_LABELS = {
17
+ bar: "Bar",
18
+ line: "Line",
19
+ area: "Area",
20
+ pie: "Pie",
21
+ donut: "Donut",
22
+ scatter: "Scatter",
23
+ radar: "Radar",
24
+ heatmap: "Heatmap"
25
+ };
13
26
  /**
14
27
  * Renders a chart + data table for a Genie query result.
15
28
  *
@@ -19,11 +32,23 @@ const CHART_HEIGHT = 250;
19
32
  */
20
33
  function GenieQueryVisualization({ data, className }) {
21
34
  const transformed = useMemo(() => transformGenieData(data), [data]);
22
- const inference = useMemo(() => transformed ? inferChartType(transformed.rows, transformed.columns) : null, [transformed]);
35
+ const { inference, compatibleTypes } = useMemo(() => {
36
+ if (!transformed) return {
37
+ inference: null,
38
+ compatibleTypes: []
39
+ };
40
+ const { rows, columns } = transformed;
41
+ return {
42
+ inference: inferChartType(rows, columns),
43
+ compatibleTypes: getCompatibleChartTypes(rows, columns)
44
+ };
45
+ }, [transformed]);
46
+ const [chartTypeOverride, setChartTypeOverride] = useState(null);
23
47
  if (!transformed || transformed.rows.length === 0) return null;
24
48
  const { rows, columns } = transformed;
25
49
  const truncated = rows.length > TABLE_ROW_LIMIT;
26
50
  const displayRows = truncated ? rows.slice(0, TABLE_ROW_LIMIT) : rows;
51
+ const activeChartType = chartTypeOverride && compatibleTypes.includes(chartTypeOverride) ? chartTypeOverride : inference?.chartType ?? null;
27
52
  const dataTable = /* @__PURE__ */ jsxs("div", {
28
53
  className: "overflow-auto max-h-[300px]",
29
54
  children: [/* @__PURE__ */ jsxs(Table, { children: [/* @__PURE__ */ jsx(TableHeader, { children: /* @__PURE__ */ jsx(TableRow, { children: columns.map((col) => /* @__PURE__ */ jsx(TableHead, { children: col.name }, col.name)) }) }), /* @__PURE__ */ jsx(TableBody, { children: displayRows.map((row, i) => /* @__PURE__ */ jsx(TableRow, { children: columns.map((col) => /* @__PURE__ */ jsx(TableCell, { children: row[col.name] != null ? String(row[col.name]) : "" }, col.name)) }, i)) })] }), truncated && /* @__PURE__ */ jsxs("p", {
@@ -37,40 +62,65 @@ function GenieQueryVisualization({ data, className }) {
37
62
  ]
38
63
  })]
39
64
  });
40
- if (!inference) return /* @__PURE__ */ jsx("div", {
65
+ if (!inference || !activeChartType) return /* @__PURE__ */ jsx("div", {
41
66
  className,
42
67
  children: dataTable
43
68
  });
44
69
  return /* @__PURE__ */ jsxs(Tabs, {
45
70
  defaultValue: "chart",
46
71
  className,
47
- children: [
48
- /* @__PURE__ */ jsxs(TabsList, { children: [/* @__PURE__ */ jsx(TabsTrigger, {
72
+ children: [/* @__PURE__ */ jsxs("div", {
73
+ className: "flex items-center justify-between",
74
+ children: [/* @__PURE__ */ jsxs(TabsList, { children: [/* @__PURE__ */ jsx(TabsTrigger, {
49
75
  value: "chart",
50
76
  children: "Chart"
51
77
  }), /* @__PURE__ */ jsx(TabsTrigger, {
52
78
  value: "table",
53
79
  children: "Table"
54
- })] }),
55
- /* @__PURE__ */ jsx(TabsContent, {
80
+ })] }), compatibleTypes.length > 1 && /* @__PURE__ */ jsxs(DropdownMenu, { children: [/* @__PURE__ */ jsx(DropdownMenuTrigger, {
81
+ asChild: true,
82
+ children: /* @__PURE__ */ jsxs(Button, {
83
+ variant: "ghost",
84
+ size: "icon-sm",
85
+ "aria-label": "Change chart type",
86
+ className: "gap-0.5",
87
+ children: [/* @__PURE__ */ jsx(BarChart3Icon, { className: "size-3.5" }), /* @__PURE__ */ jsx(ChevronDownIcon, { className: "size-3" })]
88
+ })
89
+ }), /* @__PURE__ */ jsxs(DropdownMenuContent, {
90
+ align: "end",
91
+ children: [/* @__PURE__ */ jsx(DropdownMenuLabel, { children: "Chart type" }), /* @__PURE__ */ jsx(DropdownMenuRadioGroup, {
92
+ value: activeChartType,
93
+ onValueChange: (v) => setChartTypeOverride(v),
94
+ children: compatibleTypes.map((type) => /* @__PURE__ */ jsx(DropdownMenuRadioItem, {
95
+ value: type,
96
+ children: CHART_TYPE_LABELS[type]
97
+ }, type))
98
+ })]
99
+ })] })]
100
+ }), /* @__PURE__ */ jsxs("div", {
101
+ className: "grid [&>*]:col-start-1 [&>*]:row-start-1",
102
+ children: [/* @__PURE__ */ jsx(TabsContent, {
56
103
  value: "chart",
104
+ forceMount: true,
105
+ className: "data-[state=inactive]:invisible",
57
106
  children: /* @__PURE__ */ jsx(ChartErrorBoundary, {
58
107
  fallback: dataTable,
59
108
  children: /* @__PURE__ */ jsx(BaseChart, {
60
109
  data: rows,
61
- chartType: inference.chartType,
110
+ chartType: activeChartType,
62
111
  xKey: inference.xKey,
63
112
  yKey: inference.yKey,
64
113
  height: CHART_HEIGHT,
65
114
  showLegend: Array.isArray(inference.yKey)
66
115
  })
67
116
  })
68
- }),
69
- /* @__PURE__ */ jsx(TabsContent, {
117
+ }), /* @__PURE__ */ jsx(TabsContent, {
70
118
  value: "table",
119
+ forceMount: true,
120
+ className: "data-[state=inactive]:invisible",
71
121
  children: dataTable
72
- })
73
- ]
122
+ })]
123
+ })]
74
124
  });
75
125
  }
76
126
 
@@ -1 +1 @@
1
- {"version":3,"file":"genie-query-visualization.js","names":[],"sources":["../../../src/react/genie/genie-query-visualization.tsx"],"sourcesContent":["import { useMemo } from \"react\";\nimport type { GenieStatementResponse } from \"shared\";\nimport { BaseChart } from \"../charts/base\";\nimport { ChartErrorBoundary } from \"../charts/chart-error-boundary\";\nimport {\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n} from \"../ui/table\";\nimport { Tabs, TabsContent, TabsList, TabsTrigger } from \"../ui/tabs\";\nimport { inferChartType } from \"./genie-chart-inference\";\nimport { transformGenieData } from \"./genie-query-transform\";\n\nconst TABLE_ROW_LIMIT = 50;\nconst CHART_HEIGHT = 250;\n\ninterface GenieQueryVisualizationProps {\n /** Raw statement_response from the Genie API */\n data: GenieStatementResponse;\n /** Additional CSS classes */\n className?: string;\n}\n\n/**\n * Renders a chart + data table for a Genie query result.\n *\n * - When a chart type can be inferred: shows Tabs with \"Chart\" (default) and \"Table\"\n * - When no chart fits: shows only the data table\n * - When data is empty/malformed: renders nothing\n */\nexport function GenieQueryVisualization({\n data,\n className,\n}: GenieQueryVisualizationProps) {\n const transformed = useMemo(() => transformGenieData(data), [data]);\n const inference = useMemo(\n () =>\n transformed\n ? inferChartType(transformed.rows, transformed.columns)\n : null,\n [transformed],\n );\n\n if (!transformed || transformed.rows.length === 0) return null;\n\n const { rows, columns } = transformed;\n const truncated = rows.length > TABLE_ROW_LIMIT;\n const displayRows = truncated ? rows.slice(0, TABLE_ROW_LIMIT) : rows;\n\n const dataTable = (\n <div className=\"overflow-auto max-h-[300px]\">\n <Table>\n <TableHeader>\n <TableRow>\n {columns.map((col) => (\n <TableHead key={col.name}>{col.name}</TableHead>\n ))}\n </TableRow>\n </TableHeader>\n <TableBody>\n {displayRows.map((row, i) => (\n // biome-ignore lint/suspicious/noArrayIndexKey: tabular data rows have no unique identifier\n <TableRow key={i}>\n {columns.map((col) => (\n <TableCell key={col.name}>\n {row[col.name] != null ? String(row[col.name]) : \"\"}\n </TableCell>\n ))}\n </TableRow>\n ))}\n </TableBody>\n </Table>\n {truncated && (\n <p className=\"text-xs text-muted-foreground px-2 py-1\">\n Showing {TABLE_ROW_LIMIT} of {rows.length} rows\n </p>\n )}\n </div>\n );\n\n if (!inference) {\n return <div className={className}>{dataTable}</div>;\n }\n\n return (\n <Tabs defaultValue=\"chart\" className={className}>\n <TabsList>\n <TabsTrigger value=\"chart\">Chart</TabsTrigger>\n <TabsTrigger value=\"table\">Table</TabsTrigger>\n </TabsList>\n <TabsContent value=\"chart\">\n <ChartErrorBoundary fallback={dataTable}>\n <BaseChart\n data={rows}\n chartType={inference.chartType}\n xKey={inference.xKey}\n yKey={inference.yKey}\n height={CHART_HEIGHT}\n showLegend={Array.isArray(inference.yKey)}\n />\n </ChartErrorBoundary>\n </TabsContent>\n <TabsContent value=\"table\">{dataTable}</TabsContent>\n </Tabs>\n );\n}\n"],"mappings":";;;;;;;;;;AAgBA,MAAM,kBAAkB;AACxB,MAAM,eAAe;;;;;;;;AAgBrB,SAAgB,wBAAwB,EACtC,MACA,aAC+B;CAC/B,MAAM,cAAc,cAAc,mBAAmB,KAAK,EAAE,CAAC,KAAK,CAAC;CACnE,MAAM,YAAY,cAEd,cACI,eAAe,YAAY,MAAM,YAAY,QAAQ,GACrD,MACN,CAAC,YAAY,CACd;AAED,KAAI,CAAC,eAAe,YAAY,KAAK,WAAW,EAAG,QAAO;CAE1D,MAAM,EAAE,MAAM,YAAY;CAC1B,MAAM,YAAY,KAAK,SAAS;CAChC,MAAM,cAAc,YAAY,KAAK,MAAM,GAAG,gBAAgB,GAAG;CAEjE,MAAM,YACJ,qBAAC;EAAI,WAAU;aACb,qBAAC,oBACC,oBAAC,yBACC,oBAAC,sBACE,QAAQ,KAAK,QACZ,oBAAC,uBAA0B,IAAI,QAAf,IAAI,KAA4B,CAChD,GACO,GACC,EACd,oBAAC,uBACE,YAAY,KAAK,KAAK,MAErB,oBAAC,sBACE,QAAQ,KAAK,QACZ,oBAAC,uBACE,IAAI,IAAI,SAAS,OAAO,OAAO,IAAI,IAAI,MAAM,GAAG,MADnC,IAAI,KAER,CACZ,IALW,EAMJ,CACX,GACQ,IACN,EACP,aACC,qBAAC;GAAE,WAAU;;IAA0C;IAC5C;IAAgB;IAAK,KAAK;IAAO;;IACxC;GAEF;AAGR,KAAI,CAAC,UACH,QAAO,oBAAC;EAAe;YAAY;GAAgB;AAGrD,QACE,qBAAC;EAAK,cAAa;EAAmB;;GACpC,qBAAC,uBACC,oBAAC;IAAY,OAAM;cAAQ;KAAmB,EAC9C,oBAAC;IAAY,OAAM;cAAQ;KAAmB,IACrC;GACX,oBAAC;IAAY,OAAM;cACjB,oBAAC;KAAmB,UAAU;eAC5B,oBAAC;MACC,MAAM;MACN,WAAW,UAAU;MACrB,MAAM,UAAU;MAChB,MAAM,UAAU;MAChB,QAAQ;MACR,YAAY,MAAM,QAAQ,UAAU,KAAK;OACzC;MACiB;KACT;GACd,oBAAC;IAAY,OAAM;cAAS;KAAwB;;GAC/C"}
1
+ {"version":3,"file":"genie-query-visualization.js","names":[],"sources":["../../../src/react/genie/genie-query-visualization.tsx"],"sourcesContent":["import { BarChart3Icon, ChevronDownIcon } from \"lucide-react\";\nimport { useMemo, useState } from \"react\";\nimport type { GenieStatementResponse } from \"shared\";\nimport { BaseChart } from \"../charts/base\";\nimport { ChartErrorBoundary } from \"../charts/chart-error-boundary\";\nimport type { ChartType } from \"../charts/types\";\nimport { Button } from \"../ui/button\";\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuLabel,\n DropdownMenuRadioGroup,\n DropdownMenuRadioItem,\n DropdownMenuTrigger,\n} from \"../ui/dropdown-menu\";\nimport {\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n} from \"../ui/table\";\nimport { Tabs, TabsContent, TabsList, TabsTrigger } from \"../ui/tabs\";\nimport {\n getCompatibleChartTypes,\n inferChartType,\n} from \"./genie-chart-inference\";\nimport { transformGenieData } from \"./genie-query-transform\";\n\nconst TABLE_ROW_LIMIT = 50;\nconst CHART_HEIGHT = 250;\n\nconst CHART_TYPE_LABELS: Record<ChartType, string> = {\n bar: \"Bar\",\n line: \"Line\",\n area: \"Area\",\n pie: \"Pie\",\n donut: \"Donut\",\n scatter: \"Scatter\",\n radar: \"Radar\",\n heatmap: \"Heatmap\",\n};\n\ninterface GenieQueryVisualizationProps {\n /** Raw statement_response from the Genie API */\n data: GenieStatementResponse;\n /** Additional CSS classes */\n className?: string;\n}\n\n/**\n * Renders a chart + data table for a Genie query result.\n *\n * - When a chart type can be inferred: shows Tabs with \"Chart\" (default) and \"Table\"\n * - When no chart fits: shows only the data table\n * - When data is empty/malformed: renders nothing\n */\nexport function GenieQueryVisualization({\n data,\n className,\n}: GenieQueryVisualizationProps) {\n const transformed = useMemo(() => transformGenieData(data), [data]);\n const { inference, compatibleTypes } = useMemo(() => {\n if (!transformed)\n return { inference: null, compatibleTypes: [] as ChartType[] };\n const { rows, columns } = transformed;\n return {\n inference: inferChartType(rows, columns),\n compatibleTypes: getCompatibleChartTypes(rows, columns),\n };\n }, [transformed]);\n\n const [chartTypeOverride, setChartTypeOverride] = useState<ChartType | null>(\n null,\n );\n\n if (!transformed || transformed.rows.length === 0) return null;\n\n const { rows, columns } = transformed;\n const truncated = rows.length > TABLE_ROW_LIMIT;\n const displayRows = truncated ? rows.slice(0, TABLE_ROW_LIMIT) : rows;\n\n const activeChartType =\n chartTypeOverride && compatibleTypes.includes(chartTypeOverride)\n ? chartTypeOverride\n : (inference?.chartType ?? null);\n\n const dataTable = (\n <div className=\"overflow-auto max-h-[300px]\">\n <Table>\n <TableHeader>\n <TableRow>\n {columns.map((col) => (\n <TableHead key={col.name}>{col.name}</TableHead>\n ))}\n </TableRow>\n </TableHeader>\n <TableBody>\n {displayRows.map((row, i) => (\n // biome-ignore lint/suspicious/noArrayIndexKey: tabular data rows have no unique identifier\n <TableRow key={i}>\n {columns.map((col) => (\n <TableCell key={col.name}>\n {row[col.name] != null ? String(row[col.name]) : \"\"}\n </TableCell>\n ))}\n </TableRow>\n ))}\n </TableBody>\n </Table>\n {truncated && (\n <p className=\"text-xs text-muted-foreground px-2 py-1\">\n Showing {TABLE_ROW_LIMIT} of {rows.length} rows\n </p>\n )}\n </div>\n );\n\n if (!inference || !activeChartType) {\n return <div className={className}>{dataTable}</div>;\n }\n\n return (\n <Tabs defaultValue=\"chart\" className={className}>\n <div className=\"flex items-center justify-between\">\n <TabsList>\n <TabsTrigger value=\"chart\">Chart</TabsTrigger>\n <TabsTrigger value=\"table\">Table</TabsTrigger>\n </TabsList>\n {compatibleTypes.length > 1 && (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button\n variant=\"ghost\"\n size=\"icon-sm\"\n aria-label=\"Change chart type\"\n className=\"gap-0.5\"\n >\n <BarChart3Icon className=\"size-3.5\" />\n <ChevronDownIcon className=\"size-3\" />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\">\n <DropdownMenuLabel>Chart type</DropdownMenuLabel>\n <DropdownMenuRadioGroup\n value={activeChartType}\n onValueChange={(v) => setChartTypeOverride(v as ChartType)}\n >\n {compatibleTypes.map((type) => (\n <DropdownMenuRadioItem key={type} value={type}>\n {CHART_TYPE_LABELS[type]}\n </DropdownMenuRadioItem>\n ))}\n </DropdownMenuRadioGroup>\n </DropdownMenuContent>\n </DropdownMenu>\n )}\n </div>\n <div className=\"grid [&>*]:col-start-1 [&>*]:row-start-1\">\n <TabsContent\n value=\"chart\"\n forceMount\n className=\"data-[state=inactive]:invisible\"\n >\n <ChartErrorBoundary fallback={dataTable}>\n <BaseChart\n data={rows}\n chartType={activeChartType}\n xKey={inference.xKey}\n yKey={inference.yKey}\n height={CHART_HEIGHT}\n showLegend={Array.isArray(inference.yKey)}\n />\n </ChartErrorBoundary>\n </TabsContent>\n <TabsContent\n value=\"table\"\n forceMount\n className=\"data-[state=inactive]:invisible\"\n >\n {dataTable}\n </TabsContent>\n </div>\n </Tabs>\n );\n}\n"],"mappings":";;;;;;;;;;;;;AA8BA,MAAM,kBAAkB;AACxB,MAAM,eAAe;AAErB,MAAM,oBAA+C;CACnD,KAAK;CACL,MAAM;CACN,MAAM;CACN,KAAK;CACL,OAAO;CACP,SAAS;CACT,OAAO;CACP,SAAS;CACV;;;;;;;;AAgBD,SAAgB,wBAAwB,EACtC,MACA,aAC+B;CAC/B,MAAM,cAAc,cAAc,mBAAmB,KAAK,EAAE,CAAC,KAAK,CAAC;CACnE,MAAM,EAAE,WAAW,oBAAoB,cAAc;AACnD,MAAI,CAAC,YACH,QAAO;GAAE,WAAW;GAAM,iBAAiB,EAAE;GAAiB;EAChE,MAAM,EAAE,MAAM,YAAY;AAC1B,SAAO;GACL,WAAW,eAAe,MAAM,QAAQ;GACxC,iBAAiB,wBAAwB,MAAM,QAAQ;GACxD;IACA,CAAC,YAAY,CAAC;CAEjB,MAAM,CAAC,mBAAmB,wBAAwB,SAChD,KACD;AAED,KAAI,CAAC,eAAe,YAAY,KAAK,WAAW,EAAG,QAAO;CAE1D,MAAM,EAAE,MAAM,YAAY;CAC1B,MAAM,YAAY,KAAK,SAAS;CAChC,MAAM,cAAc,YAAY,KAAK,MAAM,GAAG,gBAAgB,GAAG;CAEjE,MAAM,kBACJ,qBAAqB,gBAAgB,SAAS,kBAAkB,GAC5D,oBACC,WAAW,aAAa;CAE/B,MAAM,YACJ,qBAAC;EAAI,WAAU;aACb,qBAAC,oBACC,oBAAC,yBACC,oBAAC,sBACE,QAAQ,KAAK,QACZ,oBAAC,uBAA0B,IAAI,QAAf,IAAI,KAA4B,CAChD,GACO,GACC,EACd,oBAAC,uBACE,YAAY,KAAK,KAAK,MAErB,oBAAC,sBACE,QAAQ,KAAK,QACZ,oBAAC,uBACE,IAAI,IAAI,SAAS,OAAO,OAAO,IAAI,IAAI,MAAM,GAAG,MADnC,IAAI,KAER,CACZ,IALW,EAMJ,CACX,GACQ,IACN,EACP,aACC,qBAAC;GAAE,WAAU;;IAA0C;IAC5C;IAAgB;IAAK,KAAK;IAAO;;IACxC;GAEF;AAGR,KAAI,CAAC,aAAa,CAAC,gBACjB,QAAO,oBAAC;EAAe;YAAY;GAAgB;AAGrD,QACE,qBAAC;EAAK,cAAa;EAAmB;aACpC,qBAAC;GAAI,WAAU;cACb,qBAAC,uBACC,oBAAC;IAAY,OAAM;cAAQ;KAAmB,EAC9C,oBAAC;IAAY,OAAM;cAAQ;KAAmB,IACrC,EACV,gBAAgB,SAAS,KACxB,qBAAC,2BACC,oBAAC;IAAoB;cACnB,qBAAC;KACC,SAAQ;KACR,MAAK;KACL,cAAW;KACX,WAAU;gBAEV,oBAAC,iBAAc,WAAU,aAAa,EACtC,oBAAC,mBAAgB,WAAU,WAAW;MAC/B;KACW,EACtB,qBAAC;IAAoB,OAAM;eACzB,oBAAC,+BAAkB,eAA8B,EACjD,oBAAC;KACC,OAAO;KACP,gBAAgB,MAAM,qBAAqB,EAAe;eAEzD,gBAAgB,KAAK,SACpB,oBAAC;MAAiC,OAAO;gBACtC,kBAAkB;QADO,KAEJ,CACxB;MACqB;KACL,IACT;IAEb,EACN,qBAAC;GAAI,WAAU;cACb,oBAAC;IACC,OAAM;IACN;IACA,WAAU;cAEV,oBAAC;KAAmB,UAAU;eAC5B,oBAAC;MACC,MAAM;MACN,WAAW;MACX,MAAM,UAAU;MAChB,MAAM,UAAU;MAChB,QAAQ;MACR,YAAY,MAAM,QAAQ,UAAU,KAAK;OACzC;MACiB;KACT,EACd,oBAAC;IACC,OAAM;IACN;IACA,WAAU;cAET;KACW;IACV;GACD"}
@@ -1,6 +1,6 @@
1
1
  import { GenieAttachmentResponse, GenieMessageResponse, GenieStatementResponse, GenieStreamEvent } from "../../shared/src/genie.js";
2
2
  import { ColumnCategory, GenieColumnMeta, TransformedGenieData, transformGenieData } from "./genie-query-transform.js";
3
- import { ChartInference, inferChartType } from "./genie-chart-inference.js";
3
+ import { ChartInference, getCompatibleChartTypes, inferChartType } from "./genie-chart-inference.js";
4
4
  import { GenieChatProps, GenieChatStatus, GenieMessageItem, UseGenieChatOptions, UseGenieChatReturn } from "./types.js";
5
5
  import { GenieChat } from "./genie-chat.js";
6
6
  import { GenieChatInput } from "./genie-chat-input.js";
@@ -1,4 +1,4 @@
1
- import { inferChartType } from "./genie-chart-inference.js";
1
+ import { getCompatibleChartTypes, inferChartType } from "./genie-chart-inference.js";
2
2
  import { GenieChatInput } from "./genie-chat-input.js";
3
3
  import { transformGenieData } from "./genie-query-transform.js";
4
4
  import { GenieQueryVisualization } from "./genie-query-visualization.js";
@@ -27,7 +27,7 @@ import { FilePreviewPanel, FilePreviewPanelProps } from "./file-browser/file-pre
27
27
  import { NewFolderInput, NewFolderInputProps } from "./file-browser/new-folder-input.js";
28
28
  import "./file-browser/index.js";
29
29
  import { ColumnCategory, GenieColumnMeta, TransformedGenieData, transformGenieData } from "./genie/genie-query-transform.js";
30
- import { ChartInference, inferChartType } from "./genie/genie-chart-inference.js";
30
+ import { ChartInference, getCompatibleChartTypes, inferChartType } from "./genie/genie-chart-inference.js";
31
31
  import { GenieChatProps, GenieChatStatus, GenieMessageItem, UseGenieChatOptions, UseGenieChatReturn } from "./genie/types.js";
32
32
  import { GenieChat } from "./genie/genie-chat.js";
33
33
  import { GenieChatInput } from "./genie/genie-chat-input.js";
@@ -97,4 +97,4 @@ import { Textarea } from "./ui/textarea.js";
97
97
  import { Toggle, toggleVariants } from "./ui/toggle.js";
98
98
  import { ToggleGroup, ToggleGroupItem } from "./ui/toggle-group.js";
99
99
  import "./ui/index.js";
100
- export { Accordion, AccordionContent, AccordionItem, AccordionTrigger, Alert, AlertDescription, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, AlertTitle, AnalyticsFormat, AreaChart, AreaChartProps, AreaChartSpecificProps, AspectRatio, Avatar, AvatarFallback, AvatarImage, Badge, BarChart, BarChartProps, BarChartSpecificProps, BaseChart, BaseChartProps, Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, Button, ButtonGroup, ButtonGroupSeparator, ButtonGroupText, CHART_COLOR_VARS, CHART_COLOR_VARS_CATEGORICAL, CHART_COLOR_VARS_DIVERGING, CHART_COLOR_VARS_SEQUENTIAL, Calendar, CalendarDayButton, Card, CardAction, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Carousel, CarouselApi, CarouselContent, CarouselItem, CarouselNext, CarouselPrevious, CartesianContext, ChartBaseProps, ChartColorPalette, ChartConfig, ChartContainer, ChartData, ChartInference, ChartLegend, ChartLegendContent, ChartStyle, ChartTooltip, ChartTooltipContent, ChartType, ChartWrapper, ChartWrapperProps, Checkbox, Collapsible, CollapsibleContent, CollapsibleTrigger, ColumnCategory, Command, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator, CommandShortcut, ContextMenu, ContextMenuCheckboxItem, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuLabel, ContextMenuPortal, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuSeparator, ContextMenuShortcut, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuTrigger, DATE_FIELD_PATTERNS, DataFormat, DataProps, DataTable, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DirectoryEntry, DirectoryList, DirectoryListProps, DonutChart, DonutChartProps, Drawer, DrawerClose, DrawerContent, DrawerDescription, DrawerFooter, DrawerHeader, DrawerOverlay, DrawerPortal, DrawerTitle, DrawerTrigger, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, Empty, EmptyContent, EmptyDescription, EmptyHeader, EmptyMedia, EmptyTitle, FALLBACK_COLORS_CATEGORICAL, FALLBACK_COLORS_DIVERGING, FALLBACK_COLORS_SEQUENTIAL, Field, FieldContent, FieldDescription, FieldError, FieldGroup, FieldLabel, FieldLegend, FieldSeparator, FieldSet, FieldTitle, FileBreadcrumb, FileBreadcrumbProps, FileBrowserLabels, FileEntry, FileEntryProps, FilePreview, FilePreviewPanel, FilePreviewPanelProps, Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage, GenieAttachmentResponse, GenieChat, GenieChatInput, GenieChatMessage, GenieChatMessageList, GenieChatProps, GenieChatStatus, GenieColumnMeta, GenieMessageItem, GenieMessageResponse, GenieQueryVisualization, GenieStatementResponse, GenieStreamEvent, HeatmapChart, HeatmapChartProps, HeatmapChartSpecificProps, HeatmapContext, HoverCard, HoverCardContent, HoverCardTrigger, InferResultByFormat, InferRowType, Input, InputGroup, InputGroupAddon, InputGroupButton, InputGroupInput, InputGroupText, InputGroupTextarea, InputOTP, InputOTPGroup, InputOTPSeparator, InputOTPSlot, Item, ItemActions, ItemContent, ItemDescription, ItemFooter, ItemGroup, ItemHeader, ItemMedia, ItemSeparator, ItemTitle, Kbd, KbdGroup, Label, LineChart, LineChartProps, LineChartSpecificProps, METADATA_DATE_PATTERNS, Menubar, MenubarCheckboxItem, MenubarContent, MenubarGroup, MenubarItem, MenubarLabel, MenubarMenu, MenubarPortal, MenubarRadioGroup, MenubarRadioItem, MenubarSeparator, MenubarShortcut, MenubarSub, MenubarSubContent, MenubarSubTrigger, MenubarTrigger, NAME_FIELD_PATTERNS, NavigationMenu, NavigationMenuContent, NavigationMenuIndicator, NavigationMenuItem, NavigationMenuLink, NavigationMenuList, NavigationMenuTrigger, NavigationMenuViewport, NewFolderInput, NewFolderInputProps, NormalizedChartData, NormalizedChartDataBase, NormalizedHeatmapData, OptionBuilderContext, Orientation, Pagination, PaginationContent, PaginationEllipsis, PaginationItem, PaginationLink, PaginationNext, PaginationPrevious, PieChart, PieChartProps, PieChartSpecificProps, PluginRegistry, Popover, PopoverAnchor, PopoverContent, PopoverTrigger, PortalContainerContext, PortalContainerProvider, Progress, QueryProps, QueryRegistry, RadarChart, RadarChartProps, RadarChartSpecificProps, RadioGroup, RadioGroupItem, ResizableHandle, ResizablePanel, ResizablePanelGroup, ScatterChart, ScatterChartProps, ScatterChartSpecificProps, ScrollArea, ScrollBar, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, Separator, Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle, SheetTrigger, Sidebar, SidebarContent, SidebarFooter, SidebarGroup, SidebarGroupAction, SidebarGroupContent, SidebarGroupLabel, SidebarHeader, SidebarInput, SidebarInset, SidebarMenu, SidebarMenuAction, SidebarMenuBadge, SidebarMenuButton, SidebarMenuItem, SidebarMenuSkeleton, SidebarMenuSub, SidebarMenuSubButton, SidebarMenuSubItem, SidebarProvider, SidebarRail, SidebarSeparator, SidebarTrigger, Skeleton, Slider, Spinner, Switch, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, Textarea, Toaster, Toggle, ToggleGroup, ToggleGroupItem, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, TransformedGenieData, TypedArrowTable, UnifiedChartProps, UseAnalyticsQueryOptions, UseAnalyticsQueryResult, UseChartDataOptions, UseChartDataResult, UseGenieChatOptions, UseGenieChatReturn, badgeVariants, buildCartesianOption, buildHeatmapOption, buildHorizontalBarOption, buildPieOption, buildRadarOption, buttonGroupVariants, buttonVariants, cn, createChart, createTimeSeriesData, formatFileSize, formatLabel, inferChartType, isArrowTable, isDataProps, isQueryProps, navigationMenuTriggerStyle, normalizeChartData, normalizeHeatmapData, sortTimeSeriesAscending, toChartArray, toChartValue, toggleVariants, transformGenieData, truncateLabel, useAllThemeColors, useAnalyticsQuery, useChartData, useFormField, useGenieChat, usePortalContainer, useResolvedPortalContainer, useSidebar, useThemeColors };
100
+ export { Accordion, AccordionContent, AccordionItem, AccordionTrigger, Alert, AlertDescription, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, AlertTitle, AnalyticsFormat, AreaChart, AreaChartProps, AreaChartSpecificProps, AspectRatio, Avatar, AvatarFallback, AvatarImage, Badge, BarChart, BarChartProps, BarChartSpecificProps, BaseChart, BaseChartProps, Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, Button, ButtonGroup, ButtonGroupSeparator, ButtonGroupText, CHART_COLOR_VARS, CHART_COLOR_VARS_CATEGORICAL, CHART_COLOR_VARS_DIVERGING, CHART_COLOR_VARS_SEQUENTIAL, Calendar, CalendarDayButton, Card, CardAction, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Carousel, CarouselApi, CarouselContent, CarouselItem, CarouselNext, CarouselPrevious, CartesianContext, ChartBaseProps, ChartColorPalette, ChartConfig, ChartContainer, ChartData, ChartInference, ChartLegend, ChartLegendContent, ChartStyle, ChartTooltip, ChartTooltipContent, ChartType, ChartWrapper, ChartWrapperProps, Checkbox, Collapsible, CollapsibleContent, CollapsibleTrigger, ColumnCategory, Command, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator, CommandShortcut, ContextMenu, ContextMenuCheckboxItem, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuLabel, ContextMenuPortal, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuSeparator, ContextMenuShortcut, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuTrigger, DATE_FIELD_PATTERNS, DataFormat, DataProps, DataTable, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DirectoryEntry, DirectoryList, DirectoryListProps, DonutChart, DonutChartProps, Drawer, DrawerClose, DrawerContent, DrawerDescription, DrawerFooter, DrawerHeader, DrawerOverlay, DrawerPortal, DrawerTitle, DrawerTrigger, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, Empty, EmptyContent, EmptyDescription, EmptyHeader, EmptyMedia, EmptyTitle, FALLBACK_COLORS_CATEGORICAL, FALLBACK_COLORS_DIVERGING, FALLBACK_COLORS_SEQUENTIAL, Field, FieldContent, FieldDescription, FieldError, FieldGroup, FieldLabel, FieldLegend, FieldSeparator, FieldSet, FieldTitle, FileBreadcrumb, FileBreadcrumbProps, FileBrowserLabels, FileEntry, FileEntryProps, FilePreview, FilePreviewPanel, FilePreviewPanelProps, Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage, GenieAttachmentResponse, GenieChat, GenieChatInput, GenieChatMessage, GenieChatMessageList, GenieChatProps, GenieChatStatus, GenieColumnMeta, GenieMessageItem, GenieMessageResponse, GenieQueryVisualization, GenieStatementResponse, GenieStreamEvent, HeatmapChart, HeatmapChartProps, HeatmapChartSpecificProps, HeatmapContext, HoverCard, HoverCardContent, HoverCardTrigger, InferResultByFormat, InferRowType, Input, InputGroup, InputGroupAddon, InputGroupButton, InputGroupInput, InputGroupText, InputGroupTextarea, InputOTP, InputOTPGroup, InputOTPSeparator, InputOTPSlot, Item, ItemActions, ItemContent, ItemDescription, ItemFooter, ItemGroup, ItemHeader, ItemMedia, ItemSeparator, ItemTitle, Kbd, KbdGroup, Label, LineChart, LineChartProps, LineChartSpecificProps, METADATA_DATE_PATTERNS, Menubar, MenubarCheckboxItem, MenubarContent, MenubarGroup, MenubarItem, MenubarLabel, MenubarMenu, MenubarPortal, MenubarRadioGroup, MenubarRadioItem, MenubarSeparator, MenubarShortcut, MenubarSub, MenubarSubContent, MenubarSubTrigger, MenubarTrigger, NAME_FIELD_PATTERNS, NavigationMenu, NavigationMenuContent, NavigationMenuIndicator, NavigationMenuItem, NavigationMenuLink, NavigationMenuList, NavigationMenuTrigger, NavigationMenuViewport, NewFolderInput, NewFolderInputProps, NormalizedChartData, NormalizedChartDataBase, NormalizedHeatmapData, OptionBuilderContext, Orientation, Pagination, PaginationContent, PaginationEllipsis, PaginationItem, PaginationLink, PaginationNext, PaginationPrevious, PieChart, PieChartProps, PieChartSpecificProps, PluginRegistry, Popover, PopoverAnchor, PopoverContent, PopoverTrigger, PortalContainerContext, PortalContainerProvider, Progress, QueryProps, QueryRegistry, RadarChart, RadarChartProps, RadarChartSpecificProps, RadioGroup, RadioGroupItem, ResizableHandle, ResizablePanel, ResizablePanelGroup, ScatterChart, ScatterChartProps, ScatterChartSpecificProps, ScrollArea, ScrollBar, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, Separator, Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle, SheetTrigger, Sidebar, SidebarContent, SidebarFooter, SidebarGroup, SidebarGroupAction, SidebarGroupContent, SidebarGroupLabel, SidebarHeader, SidebarInput, SidebarInset, SidebarMenu, SidebarMenuAction, SidebarMenuBadge, SidebarMenuButton, SidebarMenuItem, SidebarMenuSkeleton, SidebarMenuSub, SidebarMenuSubButton, SidebarMenuSubItem, SidebarProvider, SidebarRail, SidebarSeparator, SidebarTrigger, Skeleton, Slider, Spinner, Switch, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, Textarea, Toaster, Toggle, ToggleGroup, ToggleGroupItem, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, TransformedGenieData, TypedArrowTable, UnifiedChartProps, UseAnalyticsQueryOptions, UseAnalyticsQueryResult, UseChartDataOptions, UseChartDataResult, UseGenieChatOptions, UseGenieChatReturn, badgeVariants, buildCartesianOption, buildHeatmapOption, buildHorizontalBarOption, buildPieOption, buildRadarOption, buttonGroupVariants, buttonVariants, cn, createChart, createTimeSeriesData, formatFileSize, formatLabel, getCompatibleChartTypes, inferChartType, isArrowTable, isDataProps, isQueryProps, navigationMenuTriggerStyle, normalizeChartData, normalizeHeatmapData, sortTimeSeriesAscending, toChartArray, toChartValue, toggleVariants, transformGenieData, truncateLabel, useAllThemeColors, useAnalyticsQuery, useChartData, useFormField, useGenieChat, usePortalContainer, useResolvedPortalContainer, useSidebar, useThemeColors };
@@ -30,11 +30,13 @@ import { FileBreadcrumb } from "./file-browser/file-breadcrumb.js";
30
30
  import { FilePreviewPanel } from "./file-browser/file-preview-panel.js";
31
31
  import { NewFolderInput } from "./file-browser/new-folder-input.js";
32
32
  import "./file-browser/index.js";
33
- import { inferChartType } from "./genie/genie-chart-inference.js";
33
+ import { getCompatibleChartTypes, inferChartType } from "./genie/genie-chart-inference.js";
34
34
  import { GenieChatInput } from "./genie/genie-chat-input.js";
35
35
  import { ScrollArea, ScrollBar } from "./ui/scroll-area.js";
36
36
  import { Spinner } from "./ui/spinner.js";
37
37
  import { Avatar, AvatarFallback, AvatarImage } from "./ui/avatar.js";
38
+ import { PortalContainerContext, PortalContainerProvider, usePortalContainer, useResolvedPortalContainer } from "./portal-container-context.js";
39
+ import { DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger } from "./ui/dropdown-menu.js";
38
40
  import { Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow } from "./ui/table.js";
39
41
  import { Tabs, TabsContent, TabsList, TabsTrigger } from "./ui/tabs.js";
40
42
  import { transformGenieData } from "./genie/genie-query-transform.js";
@@ -45,8 +47,6 @@ import { useGenieChat } from "./genie/use-genie-chat.js";
45
47
  import { GenieChat } from "./genie/genie-chat.js";
46
48
  import "./genie/index.js";
47
49
  import "./hooks/index.js";
48
- import { PortalContainerContext, PortalContainerProvider, usePortalContainer, useResolvedPortalContainer } from "./portal-container-context.js";
49
- import { DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger } from "./ui/dropdown-menu.js";
50
50
  import { Input } from "./ui/input.js";
51
51
  import { Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue } from "./ui/select.js";
52
52
  import { Checkbox } from "./ui/checkbox.js";
@@ -94,4 +94,4 @@ import { Toggle, toggleVariants } from "./ui/toggle.js";
94
94
  import { ToggleGroup, ToggleGroupItem } from "./ui/toggle-group.js";
95
95
  import "./ui/index.js";
96
96
 
97
- export { Accordion, AccordionContent, AccordionItem, AccordionTrigger, Alert, AlertDescription, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, AlertTitle, AreaChart, AspectRatio, Avatar, AvatarFallback, AvatarImage, Badge, BarChart, BaseChart, Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, Button, ButtonGroup, ButtonGroupSeparator, ButtonGroupText, CHART_COLOR_VARS, CHART_COLOR_VARS_CATEGORICAL, CHART_COLOR_VARS_DIVERGING, CHART_COLOR_VARS_SEQUENTIAL, Calendar, CalendarDayButton, Card, CardAction, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Carousel, CarouselContent, CarouselItem, CarouselNext, CarouselPrevious, ChartContainer, ChartLegend, ChartLegendContent, ChartStyle, ChartTooltip, ChartTooltipContent, ChartWrapper, Checkbox, Collapsible, CollapsibleContent, CollapsibleTrigger, Command, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator, CommandShortcut, ContextMenu, ContextMenuCheckboxItem, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuLabel, ContextMenuPortal, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuSeparator, ContextMenuShortcut, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuTrigger, DATE_FIELD_PATTERNS, DataTable, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DirectoryList, DonutChart, Drawer, DrawerClose, DrawerContent, DrawerDescription, DrawerFooter, DrawerHeader, DrawerOverlay, DrawerPortal, DrawerTitle, DrawerTrigger, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, Empty, EmptyContent, EmptyDescription, EmptyHeader, EmptyMedia, EmptyTitle, FALLBACK_COLORS_CATEGORICAL, FALLBACK_COLORS_DIVERGING, FALLBACK_COLORS_SEQUENTIAL, Field, FieldContent, FieldDescription, FieldError, FieldGroup, FieldLabel, FieldLegend, FieldSeparator, FieldSet, FieldTitle, FileBreadcrumb, FileEntry, FilePreviewPanel, Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage, GenieChat, GenieChatInput, GenieChatMessage, GenieChatMessageList, GenieQueryVisualization, HeatmapChart, HoverCard, HoverCardContent, HoverCardTrigger, Input, InputGroup, InputGroupAddon, InputGroupButton, InputGroupInput, InputGroupText, InputGroupTextarea, InputOTP, InputOTPGroup, InputOTPSeparator, InputOTPSlot, Item, ItemActions, ItemContent, ItemDescription, ItemFooter, ItemGroup, ItemHeader, ItemMedia, ItemSeparator, ItemTitle, Kbd, KbdGroup, Label, LineChart, METADATA_DATE_PATTERNS, Menubar, MenubarCheckboxItem, MenubarContent, MenubarGroup, MenubarItem, MenubarLabel, MenubarMenu, MenubarPortal, MenubarRadioGroup, MenubarRadioItem, MenubarSeparator, MenubarShortcut, MenubarSub, MenubarSubContent, MenubarSubTrigger, MenubarTrigger, NAME_FIELD_PATTERNS, NavigationMenu, NavigationMenuContent, NavigationMenuIndicator, NavigationMenuItem, NavigationMenuLink, NavigationMenuList, NavigationMenuTrigger, NavigationMenuViewport, NewFolderInput, Pagination, PaginationContent, PaginationEllipsis, PaginationItem, PaginationLink, PaginationNext, PaginationPrevious, PieChart, Popover, PopoverAnchor, PopoverContent, PopoverTrigger, PortalContainerContext, PortalContainerProvider, Progress, RadarChart, RadioGroup, RadioGroupItem, ResizableHandle, ResizablePanel, ResizablePanelGroup, ScatterChart, ScrollArea, ScrollBar, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, Separator, Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle, SheetTrigger, Sidebar, SidebarContent, SidebarFooter, SidebarGroup, SidebarGroupAction, SidebarGroupContent, SidebarGroupLabel, SidebarHeader, SidebarInput, SidebarInset, SidebarMenu, SidebarMenuAction, SidebarMenuBadge, SidebarMenuButton, SidebarMenuItem, SidebarMenuSkeleton, SidebarMenuSub, SidebarMenuSubButton, SidebarMenuSubItem, SidebarProvider, SidebarRail, SidebarSeparator, SidebarTrigger, Skeleton, Slider, Spinner, Switch, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, Textarea, Toaster, Toggle, ToggleGroup, ToggleGroupItem, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, badgeVariants, buildCartesianOption, buildHeatmapOption, buildHorizontalBarOption, buildPieOption, buildRadarOption, buttonGroupVariants, buttonVariants, cn, createChart, createTimeSeriesData, formatFileSize, formatLabel, inferChartType, isArrowTable, isDataProps, isQueryProps, navigationMenuTriggerStyle, normalizeChartData, normalizeHeatmapData, sortTimeSeriesAscending, toChartArray, toChartValue, toggleVariants, transformGenieData, truncateLabel, useAllThemeColors, useAnalyticsQuery, useChartData, useFormField, useGenieChat, usePortalContainer, useResolvedPortalContainer, useSidebar, useThemeColors };
97
+ export { Accordion, AccordionContent, AccordionItem, AccordionTrigger, Alert, AlertDescription, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, AlertTitle, AreaChart, AspectRatio, Avatar, AvatarFallback, AvatarImage, Badge, BarChart, BaseChart, Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, Button, ButtonGroup, ButtonGroupSeparator, ButtonGroupText, CHART_COLOR_VARS, CHART_COLOR_VARS_CATEGORICAL, CHART_COLOR_VARS_DIVERGING, CHART_COLOR_VARS_SEQUENTIAL, Calendar, CalendarDayButton, Card, CardAction, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Carousel, CarouselContent, CarouselItem, CarouselNext, CarouselPrevious, ChartContainer, ChartLegend, ChartLegendContent, ChartStyle, ChartTooltip, ChartTooltipContent, ChartWrapper, Checkbox, Collapsible, CollapsibleContent, CollapsibleTrigger, Command, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator, CommandShortcut, ContextMenu, ContextMenuCheckboxItem, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuLabel, ContextMenuPortal, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuSeparator, ContextMenuShortcut, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuTrigger, DATE_FIELD_PATTERNS, DataTable, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DirectoryList, DonutChart, Drawer, DrawerClose, DrawerContent, DrawerDescription, DrawerFooter, DrawerHeader, DrawerOverlay, DrawerPortal, DrawerTitle, DrawerTrigger, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, Empty, EmptyContent, EmptyDescription, EmptyHeader, EmptyMedia, EmptyTitle, FALLBACK_COLORS_CATEGORICAL, FALLBACK_COLORS_DIVERGING, FALLBACK_COLORS_SEQUENTIAL, Field, FieldContent, FieldDescription, FieldError, FieldGroup, FieldLabel, FieldLegend, FieldSeparator, FieldSet, FieldTitle, FileBreadcrumb, FileEntry, FilePreviewPanel, Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage, GenieChat, GenieChatInput, GenieChatMessage, GenieChatMessageList, GenieQueryVisualization, HeatmapChart, HoverCard, HoverCardContent, HoverCardTrigger, Input, InputGroup, InputGroupAddon, InputGroupButton, InputGroupInput, InputGroupText, InputGroupTextarea, InputOTP, InputOTPGroup, InputOTPSeparator, InputOTPSlot, Item, ItemActions, ItemContent, ItemDescription, ItemFooter, ItemGroup, ItemHeader, ItemMedia, ItemSeparator, ItemTitle, Kbd, KbdGroup, Label, LineChart, METADATA_DATE_PATTERNS, Menubar, MenubarCheckboxItem, MenubarContent, MenubarGroup, MenubarItem, MenubarLabel, MenubarMenu, MenubarPortal, MenubarRadioGroup, MenubarRadioItem, MenubarSeparator, MenubarShortcut, MenubarSub, MenubarSubContent, MenubarSubTrigger, MenubarTrigger, NAME_FIELD_PATTERNS, NavigationMenu, NavigationMenuContent, NavigationMenuIndicator, NavigationMenuItem, NavigationMenuLink, NavigationMenuList, NavigationMenuTrigger, NavigationMenuViewport, NewFolderInput, Pagination, PaginationContent, PaginationEllipsis, PaginationItem, PaginationLink, PaginationNext, PaginationPrevious, PieChart, Popover, PopoverAnchor, PopoverContent, PopoverTrigger, PortalContainerContext, PortalContainerProvider, Progress, RadarChart, RadioGroup, RadioGroupItem, ResizableHandle, ResizablePanel, ResizablePanelGroup, ScatterChart, ScrollArea, ScrollBar, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, Separator, Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle, SheetTrigger, Sidebar, SidebarContent, SidebarFooter, SidebarGroup, SidebarGroupAction, SidebarGroupContent, SidebarGroupLabel, SidebarHeader, SidebarInput, SidebarInset, SidebarMenu, SidebarMenuAction, SidebarMenuBadge, SidebarMenuButton, SidebarMenuItem, SidebarMenuSkeleton, SidebarMenuSub, SidebarMenuSubButton, SidebarMenuSubItem, SidebarProvider, SidebarRail, SidebarSeparator, SidebarTrigger, Skeleton, Slider, Spinner, Switch, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, Textarea, Toaster, Toggle, ToggleGroup, ToggleGroupItem, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, badgeVariants, buildCartesianOption, buildHeatmapOption, buildHorizontalBarOption, buildPieOption, buildRadarOption, buttonGroupVariants, buttonVariants, cn, createChart, createTimeSeriesData, formatFileSize, formatLabel, getCompatibleChartTypes, inferChartType, isArrowTable, isDataProps, isQueryProps, navigationMenuTriggerStyle, normalizeChartData, normalizeHeatmapData, sortTimeSeriesAscending, toChartArray, toChartValue, toggleVariants, transformGenieData, truncateLabel, useAllThemeColors, useAnalyticsQuery, useChartData, useFormField, useGenieChat, usePortalContainer, useResolvedPortalContainer, useSidebar, useThemeColors };
@@ -1,7 +1,7 @@
1
1
  import { formatFieldLabel } from "../lib/format.js";
2
2
  import { Button } from "../ui/button.js";
3
- import { Table as Table$1, TableBody, TableCell, TableHead, TableHeader, TableRow } from "../ui/table.js";
4
3
  import { DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuTrigger } from "../ui/dropdown-menu.js";
4
+ import { Table as Table$1, TableBody, TableCell, TableHead, TableHeader, TableRow } from "../ui/table.js";
5
5
  import { Input } from "../ui/input.js";
6
6
  import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "../ui/select.js";
7
7
  import { TableWrapper } from "./table-wrapper.js";
@@ -5,9 +5,9 @@ import { Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, Breadcr
5
5
  import { ScrollArea, ScrollBar } from "./scroll-area.js";
6
6
  import { Spinner } from "./spinner.js";
7
7
  import { Avatar, AvatarFallback, AvatarImage } from "./avatar.js";
8
+ import { DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger } from "./dropdown-menu.js";
8
9
  import { Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow } from "./table.js";
9
10
  import { Tabs, TabsContent, TabsList, TabsTrigger } from "./tabs.js";
10
- import { DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger } from "./dropdown-menu.js";
11
11
  import { Input } from "./input.js";
12
12
  import { Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue } from "./select.js";
13
13
  import { Checkbox } from "./checkbox.js";
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@databricks/appkit-ui",
3
3
  "type": "module",
4
- "version": "0.20.3",
4
+ "version": "0.21.0",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
7
7
  "type": "git",