@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.cjs
CHANGED
|
@@ -10,10 +10,13 @@ var heatmap = require('@nivo/heatmap');
|
|
|
10
10
|
var PivotTableUI = require('react-pivottable/PivotTableUI');
|
|
11
11
|
require('react-pivottable/pivottable.css');
|
|
12
12
|
var lucideReact = require('lucide-react');
|
|
13
|
+
var CodeMirror = require('@uiw/react-codemirror');
|
|
14
|
+
var langSql = require('@codemirror/lang-sql');
|
|
13
15
|
|
|
14
16
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
15
17
|
|
|
16
18
|
var PivotTableUI__default = /*#__PURE__*/_interopDefault(PivotTableUI);
|
|
19
|
+
var CodeMirror__default = /*#__PURE__*/_interopDefault(CodeMirror);
|
|
17
20
|
|
|
18
21
|
// src/context/DashboardContext.tsx
|
|
19
22
|
var DashboardContext = react.createContext(null);
|
|
@@ -649,18 +652,19 @@ var renderCell = (v) => {
|
|
|
649
652
|
if (typeof v === "boolean") return v ? "true" : "false";
|
|
650
653
|
return String(v);
|
|
651
654
|
};
|
|
652
|
-
function SqlConsole({ columns = [], stateId }) {
|
|
655
|
+
function SqlConsole({ columns = [], stateId, defaultColumnsOpen = false, defaultSql = DEFAULT_SQL, autoRun = false }) {
|
|
653
656
|
const { theme, runQuery } = useDashboard();
|
|
654
|
-
const [sql, setSql] = react.useState(
|
|
657
|
+
const [sql, setSql] = react.useState(defaultSql);
|
|
655
658
|
const [result, setResult] = react.useState(null);
|
|
656
659
|
const [error, setError] = react.useState(null);
|
|
657
660
|
const [running, setRunning] = react.useState(false);
|
|
658
|
-
const
|
|
659
|
-
|
|
661
|
+
const [columnsOpen, setColumnsOpen] = react.useState(defaultColumnsOpen);
|
|
662
|
+
const run = async (text = sql) => {
|
|
663
|
+
if (running || !text.trim()) return;
|
|
660
664
|
setRunning(true);
|
|
661
665
|
setError(null);
|
|
662
666
|
try {
|
|
663
|
-
const data = await runQuery(
|
|
667
|
+
const data = await runQuery(text, stateId);
|
|
664
668
|
setResult({ columns: data.columns || [], rows: data.rows || [] });
|
|
665
669
|
} catch (err) {
|
|
666
670
|
setResult(null);
|
|
@@ -669,12 +673,29 @@ function SqlConsole({ columns = [], stateId }) {
|
|
|
669
673
|
setRunning(false);
|
|
670
674
|
}
|
|
671
675
|
};
|
|
672
|
-
|
|
673
|
-
if (
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
676
|
+
react.useEffect(() => {
|
|
677
|
+
if (!autoRun || !stateId) return;
|
|
678
|
+
setSql(defaultSql);
|
|
679
|
+
void run(defaultSql);
|
|
680
|
+
}, [stateId, autoRun, defaultSql]);
|
|
681
|
+
const runRef = react.useRef(() => {
|
|
682
|
+
});
|
|
683
|
+
runRef.current = () => {
|
|
684
|
+
void run();
|
|
677
685
|
};
|
|
686
|
+
const schemaKey = columns.map((c) => c.name).join(",");
|
|
687
|
+
const extensions = react.useMemo(
|
|
688
|
+
() => [
|
|
689
|
+
langSql.sql({ schema: { data: columns.map((c) => c.name) }, upperCaseKeywords: true }),
|
|
690
|
+
CodeMirror.EditorView.lineWrapping,
|
|
691
|
+
CodeMirror.Prec.highest(CodeMirror.keymap.of([{ key: "Mod-Enter", run: () => {
|
|
692
|
+
runRef.current();
|
|
693
|
+
return true;
|
|
694
|
+
} }]))
|
|
695
|
+
],
|
|
696
|
+
[schemaKey]
|
|
697
|
+
// eslint-disable-line react-hooks/exhaustive-deps
|
|
698
|
+
);
|
|
678
699
|
const resultColumns = result?.columns || [];
|
|
679
700
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col h-full", children: [
|
|
680
701
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: `border-b ${theme.border} bg-midnight-elevated p-3 shrink-0`, children: [
|
|
@@ -698,30 +719,46 @@ function SqlConsole({ columns = [], stateId }) {
|
|
|
698
719
|
)
|
|
699
720
|
] }),
|
|
700
721
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
701
|
-
|
|
722
|
+
CodeMirror__default.default,
|
|
702
723
|
{
|
|
703
724
|
value: sql,
|
|
704
|
-
onChange:
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
placeholder: "SELECT ... FROM data"
|
|
725
|
+
onChange: setSql,
|
|
726
|
+
extensions,
|
|
727
|
+
theme: "dark",
|
|
728
|
+
basicSetup: { lineNumbers: false, foldGutter: false, highlightActiveLine: false },
|
|
729
|
+
height: "120px",
|
|
730
|
+
placeholder: "SELECT ... FROM data",
|
|
731
|
+
className: "border border-midnight-border text-sm overflow-hidden focus-within:border-midnight-accent"
|
|
710
732
|
}
|
|
711
733
|
),
|
|
712
|
-
columns.length > 0 && /* @__PURE__ */ jsxRuntime.
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
734
|
+
columns.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-2", children: [
|
|
735
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
736
|
+
"button",
|
|
737
|
+
{
|
|
738
|
+
onClick: () => setColumnsOpen((o) => !o),
|
|
739
|
+
className: "flex items-center gap-1 text-[11px] font-mono text-midnight-text-muted hover:text-midnight-text-body transition-colors",
|
|
740
|
+
children: [
|
|
741
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { className: `w-3 h-3 transition-transform ${columnsOpen ? "" : "-rotate-90"}` }),
|
|
742
|
+
"Columns (",
|
|
743
|
+
columns.length,
|
|
744
|
+
")"
|
|
745
|
+
]
|
|
746
|
+
}
|
|
747
|
+
),
|
|
748
|
+
columnsOpen && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1.5 flex flex-wrap gap-1", children: columns.map((c) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
749
|
+
"button",
|
|
750
|
+
{
|
|
751
|
+
title: `Insert ${c.name}`,
|
|
752
|
+
onClick: () => setSql((s) => `${s}${s.endsWith(" ") || s.endsWith("\n") || !s ? "" : " "}${c.name}`),
|
|
753
|
+
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",
|
|
754
|
+
children: [
|
|
755
|
+
c.name,
|
|
756
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "opacity-50 ml-1", children: c.type })
|
|
757
|
+
]
|
|
758
|
+
},
|
|
759
|
+
c.name
|
|
760
|
+
)) })
|
|
761
|
+
] })
|
|
725
762
|
] }),
|
|
726
763
|
(result || error) && /* @__PURE__ */ jsxRuntime.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__ */ jsxRuntime.jsxs("span", { className: "flex items-center gap-1.5", children: [
|
|
727
764
|
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertCircle, { className: "w-3.5 h-3.5" }),
|
|
@@ -1612,6 +1649,11 @@ function ModeTab({ active, onClick, icon: Icon, label }) {
|
|
|
1612
1649
|
}
|
|
1613
1650
|
);
|
|
1614
1651
|
}
|
|
1652
|
+
var MODE_TABS = [
|
|
1653
|
+
{ mode: "dashboard", icon: lucideReact.Sparkles, label: "Dashboard" },
|
|
1654
|
+
{ mode: "builder", icon: lucideReact.BarChart3, label: "Chart Builder" },
|
|
1655
|
+
{ mode: "sql", icon: lucideReact.Terminal, label: "SQL" }
|
|
1656
|
+
];
|
|
1615
1657
|
function DataExplorer({
|
|
1616
1658
|
records,
|
|
1617
1659
|
columns,
|
|
@@ -1623,12 +1665,15 @@ function DataExplorer({
|
|
|
1623
1665
|
savedDashboards = [],
|
|
1624
1666
|
loading = false,
|
|
1625
1667
|
analyzing = false,
|
|
1668
|
+
defaultMode = "dashboard",
|
|
1669
|
+
tabs = ["dashboard", "builder", "sql"],
|
|
1626
1670
|
onSelectState,
|
|
1627
1671
|
onRefreshStates
|
|
1628
1672
|
}) {
|
|
1629
1673
|
const { theme, newDashboard, addPanel, saveDashboard, listDashboards, searchDashboards, loadDashboard, deleteDashboard, analyzeDataset, refineDashboard } = useDashboard();
|
|
1630
1674
|
const caps = useCapabilities();
|
|
1631
|
-
const
|
|
1675
|
+
const visibleTabs = MODE_TABS.filter((t) => tabs.includes(t.mode));
|
|
1676
|
+
const [mode, setMode] = react.useState(tabs.includes(defaultMode) ? defaultMode : tabs[0] ?? "sql");
|
|
1632
1677
|
const [fullscreen, setFullscreen] = react.useState(false);
|
|
1633
1678
|
const [showSaved, setShowSaved] = react.useState(false);
|
|
1634
1679
|
const [saveName, setSaveName] = react.useState("");
|
|
@@ -1693,9 +1738,7 @@ function DataExplorer({
|
|
|
1693
1738
|
)
|
|
1694
1739
|
] }),
|
|
1695
1740
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1 mb-3 shrink-0", children: [
|
|
1696
|
-
/* @__PURE__ */ jsxRuntime.jsx(ModeTab, { active: mode ===
|
|
1697
|
-
/* @__PURE__ */ jsxRuntime.jsx(ModeTab, { active: mode === "builder", onClick: () => setMode("builder"), icon: lucideReact.BarChart3, label: "Chart Builder" }),
|
|
1698
|
-
/* @__PURE__ */ jsxRuntime.jsx(ModeTab, { active: mode === "sql", onClick: () => setMode("sql"), icon: lucideReact.Terminal, label: "SQL" }),
|
|
1741
|
+
visibleTabs.map((t) => /* @__PURE__ */ jsxRuntime.jsx(ModeTab, { active: mode === t.mode, onClick: () => setMode(t.mode), icon: t.icon, label: t.label }, t.mode)),
|
|
1699
1742
|
caps.canNew && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1700
1743
|
"button",
|
|
1701
1744
|
{
|