@quantumwake/terminal-ux-dashboard-components 0.1.3 → 0.1.7
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.
- package/dist/index.cjs +77 -34
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +12 -2
- package/dist/index.d.ts +12 -2
- package/dist/index.js +80 -38
- package/dist/index.js.map +1 -1
- package/package.json +15 -11
package/dist/index.d.cts
CHANGED
|
@@ -326,6 +326,9 @@ interface SqlConsoleColumn {
|
|
|
326
326
|
interface SqlConsoleProps {
|
|
327
327
|
columns?: SqlConsoleColumn[];
|
|
328
328
|
stateId?: string;
|
|
329
|
+
defaultColumnsOpen?: boolean;
|
|
330
|
+
defaultSql?: string;
|
|
331
|
+
autoRun?: boolean;
|
|
329
332
|
}
|
|
330
333
|
/**
|
|
331
334
|
* SqlConsole — a HuggingFace-style read-only SQL editor over a state's full
|
|
@@ -333,7 +336,7 @@ interface SqlConsoleProps {
|
|
|
333
336
|
* in the viewer) as a view named `data`; queries run against the entire dataset,
|
|
334
337
|
* not a client sample.
|
|
335
338
|
*/
|
|
336
|
-
declare function SqlConsole({ columns, stateId }: SqlConsoleProps): react.JSX.Element;
|
|
339
|
+
declare function SqlConsole({ columns, stateId, defaultColumnsOpen, defaultSql, autoRun }: SqlConsoleProps): react.JSX.Element;
|
|
337
340
|
|
|
338
341
|
interface PanelConfig {
|
|
339
342
|
sql?: string;
|
|
@@ -457,6 +460,7 @@ interface Dashboard {
|
|
|
457
460
|
panels?: DashboardPanel[];
|
|
458
461
|
[key: string]: unknown;
|
|
459
462
|
}
|
|
463
|
+
type Mode = 'dashboard' | 'builder' | 'sql';
|
|
460
464
|
interface DataExplorerProps {
|
|
461
465
|
/** All records for the active state (viz/builder source). Empty when not loaded. */
|
|
462
466
|
records: Row[];
|
|
@@ -478,11 +482,17 @@ interface DataExplorerProps {
|
|
|
478
482
|
loading?: boolean;
|
|
479
483
|
/** True while the AI is generating/refining the dashboard. */
|
|
480
484
|
analyzing?: boolean;
|
|
485
|
+
/** Initial mode tab. Defaults to 'dashboard'; the published viewer uses 'sql'
|
|
486
|
+
* so the SQL console is the primary surface. Clamped to `tabs`. */
|
|
487
|
+
defaultMode?: Mode;
|
|
488
|
+
/** Which mode tabs to show, in order. Defaults to all three. Pass a subset to
|
|
489
|
+
* turn tabs off (e.g. ['sql'] for a SQL-only explorer). */
|
|
490
|
+
tabs?: Mode[];
|
|
481
491
|
/** Select a state (host fetches its profile/records). */
|
|
482
492
|
onSelectState: (id: string) => void;
|
|
483
493
|
/** Refresh the states catalog. */
|
|
484
494
|
onRefreshStates?: () => void;
|
|
485
495
|
}
|
|
486
|
-
declare function DataExplorer({ records, columns, states, activeStateId, profile, dashboard, dashboardId, savedDashboards, loading, analyzing, onSelectState, onRefreshStates, }: DataExplorerProps): react.JSX.Element;
|
|
496
|
+
declare function DataExplorer({ records, columns, states, activeStateId, profile, dashboard, dashboardId, savedDashboards, loading, analyzing, defaultMode, tabs, onSelectState, onRefreshStates, }: DataExplorerProps): react.JSX.Element;
|
|
487
497
|
|
|
488
498
|
export { type AggFn, type BarDatum, BarView, type BarViewProps, ChartBuilder, type ChartBuilderColumn, type ChartBuilderProps, type ChartConfig, type ChartField, type ChartFilter, type ChartPanel, type ChartStyle, ChartStyleControls, type ChartStyleControlsProps, type ChartType, DEFAULT_CHART_STYLE, type Dashboard$1 as Dashboard, type DashboardCapabilities, type DashboardContextValue, type DashboardPanel$1 as DashboardPanel, DashboardProvider, type DashboardProviderProps, DashboardRenderer, type DashboardRendererProps, type DashboardTheme, DataExplorer, type DataExplorerProps, type HeatmapSerie, HeatmapView, type HeatmapViewProps, type InsightConfig, InsightView, type InsightViewProps, LEGEND_ANCHORS, type LegendAnchor, type LegendPosition, type LineSerie, LineView, type LineViewProps, type MetricConfig, MetricView, type MetricViewProps, type PanelInput, type PieDatum, PieView, type PieViewProps, PivotView, type PivotViewProps, type QueryResult, type Row, type SavedDashboard, type ScatterSerie, ScatterView, type ScatterViewProps, SqlConsole, type SqlConsoleColumn, type SqlConsoleProps, type TitleAlign, aggExpr, aggregate, axisLegend, buildChartSQL, buildNivoTheme, compileWhere, groupBy, legendConfig, qIdent, qLit, shapeChartData, useCapabilities, useDashboard, withStyleDefaults };
|
package/dist/index.d.ts
CHANGED
|
@@ -326,6 +326,9 @@ interface SqlConsoleColumn {
|
|
|
326
326
|
interface SqlConsoleProps {
|
|
327
327
|
columns?: SqlConsoleColumn[];
|
|
328
328
|
stateId?: string;
|
|
329
|
+
defaultColumnsOpen?: boolean;
|
|
330
|
+
defaultSql?: string;
|
|
331
|
+
autoRun?: boolean;
|
|
329
332
|
}
|
|
330
333
|
/**
|
|
331
334
|
* SqlConsole — a HuggingFace-style read-only SQL editor over a state's full
|
|
@@ -333,7 +336,7 @@ interface SqlConsoleProps {
|
|
|
333
336
|
* in the viewer) as a view named `data`; queries run against the entire dataset,
|
|
334
337
|
* not a client sample.
|
|
335
338
|
*/
|
|
336
|
-
declare function SqlConsole({ columns, stateId }: SqlConsoleProps): react.JSX.Element;
|
|
339
|
+
declare function SqlConsole({ columns, stateId, defaultColumnsOpen, defaultSql, autoRun }: SqlConsoleProps): react.JSX.Element;
|
|
337
340
|
|
|
338
341
|
interface PanelConfig {
|
|
339
342
|
sql?: string;
|
|
@@ -457,6 +460,7 @@ interface Dashboard {
|
|
|
457
460
|
panels?: DashboardPanel[];
|
|
458
461
|
[key: string]: unknown;
|
|
459
462
|
}
|
|
463
|
+
type Mode = 'dashboard' | 'builder' | 'sql';
|
|
460
464
|
interface DataExplorerProps {
|
|
461
465
|
/** All records for the active state (viz/builder source). Empty when not loaded. */
|
|
462
466
|
records: Row[];
|
|
@@ -478,11 +482,17 @@ interface DataExplorerProps {
|
|
|
478
482
|
loading?: boolean;
|
|
479
483
|
/** True while the AI is generating/refining the dashboard. */
|
|
480
484
|
analyzing?: boolean;
|
|
485
|
+
/** Initial mode tab. Defaults to 'dashboard'; the published viewer uses 'sql'
|
|
486
|
+
* so the SQL console is the primary surface. Clamped to `tabs`. */
|
|
487
|
+
defaultMode?: Mode;
|
|
488
|
+
/** Which mode tabs to show, in order. Defaults to all three. Pass a subset to
|
|
489
|
+
* turn tabs off (e.g. ['sql'] for a SQL-only explorer). */
|
|
490
|
+
tabs?: Mode[];
|
|
481
491
|
/** Select a state (host fetches its profile/records). */
|
|
482
492
|
onSelectState: (id: string) => void;
|
|
483
493
|
/** Refresh the states catalog. */
|
|
484
494
|
onRefreshStates?: () => void;
|
|
485
495
|
}
|
|
486
|
-
declare function DataExplorer({ records, columns, states, activeStateId, profile, dashboard, dashboardId, savedDashboards, loading, analyzing, onSelectState, onRefreshStates, }: DataExplorerProps): react.JSX.Element;
|
|
496
|
+
declare function DataExplorer({ records, columns, states, activeStateId, profile, dashboard, dashboardId, savedDashboards, loading, analyzing, defaultMode, tabs, onSelectState, onRefreshStates, }: DataExplorerProps): react.JSX.Element;
|
|
487
497
|
|
|
488
498
|
export { type AggFn, type BarDatum, BarView, type BarViewProps, ChartBuilder, type ChartBuilderColumn, type ChartBuilderProps, type ChartConfig, type ChartField, type ChartFilter, type ChartPanel, type ChartStyle, ChartStyleControls, type ChartStyleControlsProps, type ChartType, DEFAULT_CHART_STYLE, type Dashboard$1 as Dashboard, type DashboardCapabilities, type DashboardContextValue, type DashboardPanel$1 as DashboardPanel, DashboardProvider, type DashboardProviderProps, DashboardRenderer, type DashboardRendererProps, type DashboardTheme, DataExplorer, type DataExplorerProps, type HeatmapSerie, HeatmapView, type HeatmapViewProps, type InsightConfig, InsightView, type InsightViewProps, LEGEND_ANCHORS, type LegendAnchor, type LegendPosition, type LineSerie, LineView, type LineViewProps, type MetricConfig, MetricView, type MetricViewProps, type PanelInput, type PieDatum, PieView, type PieViewProps, PivotView, type PivotViewProps, type QueryResult, type Row, type SavedDashboard, type ScatterSerie, ScatterView, type ScatterViewProps, SqlConsole, type SqlConsoleColumn, type SqlConsoleProps, type TitleAlign, aggExpr, aggregate, axisLegend, buildChartSQL, buildNivoTheme, compileWhere, groupBy, legendConfig, qIdent, qLit, shapeChartData, useCapabilities, useDashboard, withStyleDefaults };
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createContext, useContext, useMemo, useState,
|
|
1
|
+
import { createContext, useContext, useMemo, useState, useEffect, useRef, Suspense } from 'react';
|
|
2
2
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
3
3
|
import { ResponsiveBar } from '@nivo/bar';
|
|
4
4
|
import { ResponsivePie } from '@nivo/pie';
|
|
@@ -7,7 +7,9 @@ import { ResponsiveScatterPlot } from '@nivo/scatterplot';
|
|
|
7
7
|
import { ResponsiveHeatMap } from '@nivo/heatmap';
|
|
8
8
|
import PivotTableUI from 'react-pivottable/PivotTableUI';
|
|
9
9
|
import 'react-pivottable/pivottable.css';
|
|
10
|
-
import { Loader2, Play, AlertCircle, Rows3, BarChart3, PieChart, TrendingUp, ScatterChart, LayoutGrid, Code,
|
|
10
|
+
import { Loader2, Play, ChevronDown, AlertCircle, Rows3, BarChart3, PieChart, TrendingUp, ScatterChart, LayoutGrid, Code, Sparkles, X, Terminal, RefreshCw, Minimize2, Maximize2, Plus, Save, FolderOpen, Trash2, Filter, Database, Send, GripVertical } from 'lucide-react';
|
|
11
|
+
import CodeMirror, { EditorView, Prec, keymap } from '@uiw/react-codemirror';
|
|
12
|
+
import { sql } from '@codemirror/lang-sql';
|
|
11
13
|
|
|
12
14
|
// src/context/DashboardContext.tsx
|
|
13
15
|
var DashboardContext = createContext(null);
|
|
@@ -643,18 +645,19 @@ var renderCell = (v) => {
|
|
|
643
645
|
if (typeof v === "boolean") return v ? "true" : "false";
|
|
644
646
|
return String(v);
|
|
645
647
|
};
|
|
646
|
-
function SqlConsole({ columns = [], stateId }) {
|
|
648
|
+
function SqlConsole({ columns = [], stateId, defaultColumnsOpen = false, defaultSql = DEFAULT_SQL, autoRun = false }) {
|
|
647
649
|
const { theme, runQuery } = useDashboard();
|
|
648
|
-
const [sql, setSql] = useState(
|
|
650
|
+
const [sql$1, setSql] = useState(defaultSql);
|
|
649
651
|
const [result, setResult] = useState(null);
|
|
650
652
|
const [error, setError] = useState(null);
|
|
651
653
|
const [running, setRunning] = useState(false);
|
|
652
|
-
const
|
|
653
|
-
|
|
654
|
+
const [columnsOpen, setColumnsOpen] = useState(defaultColumnsOpen);
|
|
655
|
+
const run = async (text = sql$1) => {
|
|
656
|
+
if (running || !text.trim()) return;
|
|
654
657
|
setRunning(true);
|
|
655
658
|
setError(null);
|
|
656
659
|
try {
|
|
657
|
-
const data = await runQuery(
|
|
660
|
+
const data = await runQuery(text, stateId);
|
|
658
661
|
setResult({ columns: data.columns || [], rows: data.rows || [] });
|
|
659
662
|
} catch (err) {
|
|
660
663
|
setResult(null);
|
|
@@ -663,12 +666,29 @@ function SqlConsole({ columns = [], stateId }) {
|
|
|
663
666
|
setRunning(false);
|
|
664
667
|
}
|
|
665
668
|
};
|
|
666
|
-
|
|
667
|
-
if (
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
669
|
+
useEffect(() => {
|
|
670
|
+
if (!autoRun || !stateId) return;
|
|
671
|
+
setSql(defaultSql);
|
|
672
|
+
void run(defaultSql);
|
|
673
|
+
}, [stateId, autoRun, defaultSql]);
|
|
674
|
+
const runRef = useRef(() => {
|
|
675
|
+
});
|
|
676
|
+
runRef.current = () => {
|
|
677
|
+
void run();
|
|
671
678
|
};
|
|
679
|
+
const schemaKey = columns.map((c) => c.name).join(",");
|
|
680
|
+
const extensions = useMemo(
|
|
681
|
+
() => [
|
|
682
|
+
sql({ schema: { data: columns.map((c) => c.name) }, upperCaseKeywords: true }),
|
|
683
|
+
EditorView.lineWrapping,
|
|
684
|
+
Prec.highest(keymap.of([{ key: "Mod-Enter", run: () => {
|
|
685
|
+
runRef.current();
|
|
686
|
+
return true;
|
|
687
|
+
} }]))
|
|
688
|
+
],
|
|
689
|
+
[schemaKey]
|
|
690
|
+
// eslint-disable-line react-hooks/exhaustive-deps
|
|
691
|
+
);
|
|
672
692
|
const resultColumns = result?.columns || [];
|
|
673
693
|
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col h-full", children: [
|
|
674
694
|
/* @__PURE__ */ jsxs("div", { className: `border-b ${theme.border} bg-midnight-elevated p-3 shrink-0`, children: [
|
|
@@ -681,7 +701,7 @@ function SqlConsole({ columns = [], stateId }) {
|
|
|
681
701
|
"button",
|
|
682
702
|
{
|
|
683
703
|
onClick: () => void run(),
|
|
684
|
-
disabled: running || !sql.trim(),
|
|
704
|
+
disabled: running || !sql$1.trim(),
|
|
685
705
|
className: `flex items-center gap-1.5 px-3 py-1 border text-xs font-mono transition-colors ${running ? "border-midnight-border opacity-50" : "border-midnight-accent text-midnight-accent hover:bg-midnight-accent/10"}`,
|
|
686
706
|
children: [
|
|
687
707
|
running ? /* @__PURE__ */ jsx(Loader2, { className: "w-3.5 h-3.5 animate-spin" }) : /* @__PURE__ */ jsx(Play, { className: "w-3.5 h-3.5" }),
|
|
@@ -692,30 +712,46 @@ function SqlConsole({ columns = [], stateId }) {
|
|
|
692
712
|
)
|
|
693
713
|
] }),
|
|
694
714
|
/* @__PURE__ */ jsx(
|
|
695
|
-
|
|
715
|
+
CodeMirror,
|
|
696
716
|
{
|
|
697
|
-
value: sql,
|
|
698
|
-
onChange:
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
placeholder: "SELECT ... FROM data"
|
|
717
|
+
value: sql$1,
|
|
718
|
+
onChange: setSql,
|
|
719
|
+
extensions,
|
|
720
|
+
theme: "dark",
|
|
721
|
+
basicSetup: { lineNumbers: false, foldGutter: false, highlightActiveLine: false },
|
|
722
|
+
height: "120px",
|
|
723
|
+
placeholder: "SELECT ... FROM data",
|
|
724
|
+
className: "border border-midnight-border text-sm overflow-hidden focus-within:border-midnight-accent"
|
|
704
725
|
}
|
|
705
726
|
),
|
|
706
|
-
columns.length > 0 && /* @__PURE__ */
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
727
|
+
columns.length > 0 && /* @__PURE__ */ jsxs("div", { className: "mt-2", children: [
|
|
728
|
+
/* @__PURE__ */ jsxs(
|
|
729
|
+
"button",
|
|
730
|
+
{
|
|
731
|
+
onClick: () => setColumnsOpen((o) => !o),
|
|
732
|
+
className: "flex items-center gap-1 text-[11px] font-mono text-midnight-text-muted hover:text-midnight-text-body transition-colors",
|
|
733
|
+
children: [
|
|
734
|
+
/* @__PURE__ */ jsx(ChevronDown, { className: `w-3 h-3 transition-transform ${columnsOpen ? "" : "-rotate-90"}` }),
|
|
735
|
+
"Columns (",
|
|
736
|
+
columns.length,
|
|
737
|
+
")"
|
|
738
|
+
]
|
|
739
|
+
}
|
|
740
|
+
),
|
|
741
|
+
columnsOpen && /* @__PURE__ */ jsx("div", { className: "mt-1.5 flex flex-wrap gap-1", children: columns.map((c) => /* @__PURE__ */ jsxs(
|
|
742
|
+
"button",
|
|
743
|
+
{
|
|
744
|
+
title: `Insert ${c.name}`,
|
|
745
|
+
onClick: () => setSql((s) => `${s}${s.endsWith(" ") || s.endsWith("\n") || !s ? "" : " "}${c.name}`),
|
|
746
|
+
className: "px-1.5 py-0.5 border border-midnight-border text-[11px] font-mono text-midnight-text-muted hover:bg-midnight-raised transition-colors",
|
|
747
|
+
children: [
|
|
748
|
+
c.name,
|
|
749
|
+
/* @__PURE__ */ jsx("span", { className: "opacity-50 ml-1", children: c.type })
|
|
750
|
+
]
|
|
751
|
+
},
|
|
752
|
+
c.name
|
|
753
|
+
)) })
|
|
754
|
+
] })
|
|
719
755
|
] }),
|
|
720
756
|
(result || error) && /* @__PURE__ */ jsx("div", { className: `flex items-center gap-4 px-3 py-1.5 border-b ${theme.border} text-xs font-mono shrink-0 ${error ? "text-red-400" : "text-midnight-text-muted"}`, children: error ? /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1.5", children: [
|
|
721
757
|
/* @__PURE__ */ jsx(AlertCircle, { className: "w-3.5 h-3.5" }),
|
|
@@ -1606,6 +1642,11 @@ function ModeTab({ active, onClick, icon: Icon, label }) {
|
|
|
1606
1642
|
}
|
|
1607
1643
|
);
|
|
1608
1644
|
}
|
|
1645
|
+
var MODE_TABS = [
|
|
1646
|
+
{ mode: "dashboard", icon: Sparkles, label: "Dashboard" },
|
|
1647
|
+
{ mode: "builder", icon: BarChart3, label: "Chart Builder" },
|
|
1648
|
+
{ mode: "sql", icon: Terminal, label: "SQL" }
|
|
1649
|
+
];
|
|
1609
1650
|
function DataExplorer({
|
|
1610
1651
|
records,
|
|
1611
1652
|
columns,
|
|
@@ -1617,12 +1658,15 @@ function DataExplorer({
|
|
|
1617
1658
|
savedDashboards = [],
|
|
1618
1659
|
loading = false,
|
|
1619
1660
|
analyzing = false,
|
|
1661
|
+
defaultMode = "dashboard",
|
|
1662
|
+
tabs = ["dashboard", "builder", "sql"],
|
|
1620
1663
|
onSelectState,
|
|
1621
1664
|
onRefreshStates
|
|
1622
1665
|
}) {
|
|
1623
1666
|
const { theme, newDashboard, addPanel, saveDashboard, listDashboards, searchDashboards, loadDashboard, deleteDashboard, analyzeDataset, refineDashboard } = useDashboard();
|
|
1624
1667
|
const caps = useCapabilities();
|
|
1625
|
-
const
|
|
1668
|
+
const visibleTabs = MODE_TABS.filter((t) => tabs.includes(t.mode));
|
|
1669
|
+
const [mode, setMode] = useState(tabs.includes(defaultMode) ? defaultMode : tabs[0] ?? "sql");
|
|
1626
1670
|
const [fullscreen, setFullscreen] = useState(false);
|
|
1627
1671
|
const [showSaved, setShowSaved] = useState(false);
|
|
1628
1672
|
const [saveName, setSaveName] = useState("");
|
|
@@ -1687,9 +1731,7 @@ function DataExplorer({
|
|
|
1687
1731
|
)
|
|
1688
1732
|
] }),
|
|
1689
1733
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1 mb-3 shrink-0", children: [
|
|
1690
|
-
/* @__PURE__ */ jsx(ModeTab, { active: mode ===
|
|
1691
|
-
/* @__PURE__ */ jsx(ModeTab, { active: mode === "builder", onClick: () => setMode("builder"), icon: BarChart3, label: "Chart Builder" }),
|
|
1692
|
-
/* @__PURE__ */ jsx(ModeTab, { active: mode === "sql", onClick: () => setMode("sql"), icon: Terminal, label: "SQL" }),
|
|
1734
|
+
visibleTabs.map((t) => /* @__PURE__ */ jsx(ModeTab, { active: mode === t.mode, onClick: () => setMode(t.mode), icon: t.icon, label: t.label }, t.mode)),
|
|
1693
1735
|
caps.canNew && /* @__PURE__ */ jsxs(
|
|
1694
1736
|
"button",
|
|
1695
1737
|
{
|