@quantumwake/terminal-ux-dashboard-components 0.1.5 → 0.1.8

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 CHANGED
@@ -10,10 +10,14 @@ 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');
15
+ var autocomplete = require('@codemirror/autocomplete');
13
16
 
14
17
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
15
18
 
16
19
  var PivotTableUI__default = /*#__PURE__*/_interopDefault(PivotTableUI);
20
+ var CodeMirror__default = /*#__PURE__*/_interopDefault(CodeMirror);
17
21
 
18
22
  // src/context/DashboardContext.tsx
19
23
  var DashboardContext = react.createContext(null);
@@ -642,6 +646,280 @@ function ChartStyleControls({ style, onChange }) {
642
646
  ] })
643
647
  ] });
644
648
  }
649
+ var AGGREGATES = [
650
+ "count",
651
+ "count_if",
652
+ "sum",
653
+ "avg",
654
+ "min",
655
+ "max",
656
+ "median",
657
+ "mode",
658
+ "stddev",
659
+ "stddev_pop",
660
+ "stddev_samp",
661
+ "var_pop",
662
+ "var_samp",
663
+ "variance",
664
+ "quantile",
665
+ "quantile_cont",
666
+ "quantile_disc",
667
+ "approx_count_distinct",
668
+ "approx_quantile",
669
+ "arg_max",
670
+ "arg_min",
671
+ "first",
672
+ "last",
673
+ "product",
674
+ "bool_and",
675
+ "bool_or",
676
+ "bit_and",
677
+ "bit_or",
678
+ "bit_xor",
679
+ "string_agg",
680
+ "list",
681
+ "array_agg",
682
+ "histogram",
683
+ "corr",
684
+ "covar_pop",
685
+ "covar_samp",
686
+ "kurtosis",
687
+ "skewness",
688
+ "entropy",
689
+ "row_number",
690
+ "rank",
691
+ "dense_rank",
692
+ "percent_rank",
693
+ "cume_dist",
694
+ "ntile",
695
+ "lag",
696
+ "lead",
697
+ "first_value",
698
+ "last_value",
699
+ "nth_value"
700
+ ];
701
+ var SCALARS = [
702
+ // string
703
+ "length",
704
+ "len",
705
+ "lower",
706
+ "upper",
707
+ "trim",
708
+ "ltrim",
709
+ "rtrim",
710
+ "substring",
711
+ "substr",
712
+ "concat",
713
+ "concat_ws",
714
+ "replace",
715
+ "reverse",
716
+ "repeat",
717
+ "lpad",
718
+ "rpad",
719
+ "left",
720
+ "right",
721
+ "contains",
722
+ "starts_with",
723
+ "ends_with",
724
+ "position",
725
+ "split_part",
726
+ "string_split",
727
+ "regexp_matches",
728
+ "regexp_replace",
729
+ "regexp_extract",
730
+ "regexp_full_match",
731
+ "regexp_split_to_array",
732
+ "format",
733
+ "printf",
734
+ "md5",
735
+ "sha256",
736
+ "levenshtein",
737
+ "jaccard",
738
+ "ascii",
739
+ "chr",
740
+ // date / time
741
+ "now",
742
+ "current_date",
743
+ "current_timestamp",
744
+ "today",
745
+ "date_trunc",
746
+ "date_part",
747
+ "date_diff",
748
+ "date_add",
749
+ "date_sub",
750
+ "age",
751
+ "strftime",
752
+ "strptime",
753
+ "epoch",
754
+ "epoch_ms",
755
+ "extract",
756
+ "make_date",
757
+ "make_time",
758
+ "make_timestamp",
759
+ "last_day",
760
+ "dayname",
761
+ "monthname",
762
+ "year",
763
+ "month",
764
+ "day",
765
+ "hour",
766
+ "minute",
767
+ "second",
768
+ "dayofweek",
769
+ "dayofyear",
770
+ "week",
771
+ "quarter",
772
+ "time_bucket",
773
+ // math
774
+ "abs",
775
+ "ceil",
776
+ "ceiling",
777
+ "floor",
778
+ "round",
779
+ "trunc",
780
+ "sign",
781
+ "mod",
782
+ "pow",
783
+ "power",
784
+ "sqrt",
785
+ "cbrt",
786
+ "exp",
787
+ "ln",
788
+ "log",
789
+ "log2",
790
+ "log10",
791
+ "greatest",
792
+ "least",
793
+ "gcd",
794
+ "lcm",
795
+ "factorial",
796
+ "random",
797
+ "pi",
798
+ "degrees",
799
+ "radians",
800
+ "sin",
801
+ "cos",
802
+ "tan",
803
+ "asin",
804
+ "acos",
805
+ "atan",
806
+ "atan2",
807
+ // conditional / null / cast
808
+ "coalesce",
809
+ "ifnull",
810
+ "nullif",
811
+ "nvl",
812
+ "if",
813
+ "try_cast",
814
+ "cast",
815
+ "typeof",
816
+ // list / struct / map / json
817
+ "list_value",
818
+ "list_aggregate",
819
+ "list_distinct",
820
+ "list_sort",
821
+ "list_reverse",
822
+ "list_slice",
823
+ "list_concat",
824
+ "list_contains",
825
+ "list_position",
826
+ "list_extract",
827
+ "list_transform",
828
+ "list_filter",
829
+ "unnest",
830
+ "array_length",
831
+ "array_to_string",
832
+ "struct_pack",
833
+ "struct_extract",
834
+ "map",
835
+ "map_keys",
836
+ "map_values",
837
+ "json_extract",
838
+ "json_extract_string",
839
+ "to_json",
840
+ "from_json",
841
+ "json_array_length",
842
+ "json_keys",
843
+ "generate_series",
844
+ "range"
845
+ ];
846
+ var TYPES = [
847
+ "BOOLEAN",
848
+ "TINYINT",
849
+ "SMALLINT",
850
+ "INTEGER",
851
+ "BIGINT",
852
+ "HUGEINT",
853
+ "UTINYINT",
854
+ "USMALLINT",
855
+ "UINTEGER",
856
+ "UBIGINT",
857
+ "FLOAT",
858
+ "REAL",
859
+ "DOUBLE",
860
+ "DECIMAL",
861
+ "NUMERIC",
862
+ "VARCHAR",
863
+ "CHAR",
864
+ "TEXT",
865
+ "BLOB",
866
+ "BIT",
867
+ "DATE",
868
+ "TIME",
869
+ "TIMESTAMP",
870
+ "TIMESTAMPTZ",
871
+ "INTERVAL",
872
+ "UUID",
873
+ "JSON",
874
+ "LIST",
875
+ "ARRAY",
876
+ "STRUCT",
877
+ "MAP",
878
+ "UNION",
879
+ "ENUM"
880
+ ];
881
+ var EXTRA_KEYWORDS = [
882
+ "QUALIFY",
883
+ "EXCLUDE",
884
+ "PIVOT",
885
+ "UNPIVOT",
886
+ "ASOF",
887
+ "POSITIONAL",
888
+ "SEMI",
889
+ "ANTI",
890
+ "SUMMARIZE",
891
+ "DISTINCT ON",
892
+ "GROUP BY ALL",
893
+ "ORDER BY ALL",
894
+ "USING SAMPLE"
895
+ ];
896
+ function opts(labels, type, boost = 0) {
897
+ return labels.map((label) => ({ label, type, boost }));
898
+ }
899
+ var SNIPPETS = [
900
+ autocomplete.snippetCompletion("SELECT ${col}, count(*) AS n\nFROM data\nGROUP BY ${col}\nORDER BY n DESC", {
901
+ label: "group by count",
902
+ type: "snippet",
903
+ detail: "aggregate by column"
904
+ }),
905
+ autocomplete.snippetCompletion("SELECT *\nFROM data\nORDER BY ${col} DESC\nLIMIT 10", {
906
+ label: "top N",
907
+ type: "snippet",
908
+ detail: "order + limit"
909
+ }),
910
+ autocomplete.snippetCompletion("SELECT DISTINCT ${col}\nFROM data", {
911
+ label: "select distinct",
912
+ type: "snippet"
913
+ })
914
+ ];
915
+ var duckdbCompletionSource = autocomplete.completeFromList([
916
+ ...opts(AGGREGATES, "function", 1),
917
+ // boost aggregates slightly — common in analysis
918
+ ...opts(SCALARS, "function"),
919
+ ...opts(TYPES, "type"),
920
+ ...opts(EXTRA_KEYWORDS, "keyword"),
921
+ ...SNIPPETS
922
+ ]);
645
923
  var DEFAULT_SQL = "SELECT *\nFROM data\nLIMIT 100";
646
924
  var renderCell = (v) => {
647
925
  if (v == null) return "";
@@ -675,12 +953,38 @@ function SqlConsole({ columns = [], stateId, defaultColumnsOpen = false, default
675
953
  setSql(defaultSql);
676
954
  void run(defaultSql);
677
955
  }, [stateId, autoRun, defaultSql]);
678
- const onKeyDown = (e) => {
679
- if ((e.metaKey || e.ctrlKey) && e.key === "Enter") {
680
- e.preventDefault();
681
- void run();
682
- }
956
+ const runRef = react.useRef(() => {
957
+ });
958
+ runRef.current = () => {
959
+ void run();
683
960
  };
961
+ const schemaKey = columns.map((c) => c.name).join(",");
962
+ const extensions = react.useMemo(() => {
963
+ const sqlConfig = {
964
+ dialect: langSql.PostgreSQL,
965
+ schema: { data: columns.map((c) => c.name) },
966
+ defaultTable: "data",
967
+ upperCaseKeywords: true
968
+ };
969
+ return [
970
+ langSql.sql(sqlConfig),
971
+ autocomplete.autocompletion({
972
+ override: [
973
+ langSql.schemaCompletionSource(sqlConfig),
974
+ langSql.keywordCompletionSource(langSql.PostgreSQL, true),
975
+ duckdbCompletionSource
976
+ ]
977
+ }),
978
+ CodeMirror.EditorView.lineWrapping,
979
+ CodeMirror.Prec.highest(CodeMirror.keymap.of([
980
+ { key: "Mod-Enter", run: () => {
981
+ runRef.current();
982
+ return true;
983
+ } },
984
+ { key: "Tab", run: autocomplete.acceptCompletion }
985
+ ]))
986
+ ];
987
+ }, [schemaKey]);
684
988
  const resultColumns = result?.columns || [];
685
989
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col h-full", children: [
686
990
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `border-b ${theme.border} bg-midnight-elevated p-3 shrink-0`, children: [
@@ -704,15 +1008,16 @@ function SqlConsole({ columns = [], stateId, defaultColumnsOpen = false, default
704
1008
  )
705
1009
  ] }),
706
1010
  /* @__PURE__ */ jsxRuntime.jsx(
707
- "textarea",
1011
+ CodeMirror__default.default,
708
1012
  {
709
1013
  value: sql,
710
- onChange: (e) => setSql(e.target.value),
711
- onKeyDown,
712
- spellCheck: false,
713
- rows: 5,
714
- className: "w-full bg-midnight-surface border border-midnight-border px-3 py-2 text-sm font-mono outline-none text-midnight-text-body resize-y focus:border-midnight-accent transition-colors",
715
- placeholder: "SELECT ... FROM data"
1014
+ onChange: setSql,
1015
+ extensions,
1016
+ theme: "dark",
1017
+ basicSetup: { lineNumbers: false, foldGutter: false, highlightActiveLine: false, autocompletion: false },
1018
+ height: "120px",
1019
+ placeholder: "SELECT ... FROM data",
1020
+ className: "border border-midnight-border text-sm overflow-hidden focus-within:border-midnight-accent"
716
1021
  }
717
1022
  ),
718
1023
  columns.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-2", children: [