@contractspec/example.analytics-dashboard 3.8.0 → 3.9.2

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.
@@ -682,99 +682,188 @@ function gridSpanClass(gridWidth) {
682
682
  }
683
683
 
684
684
  // src/ui/AnalyticsQueriesTable.tsx
685
+ import { DataTable } from "@contractspec/lib.design-system";
686
+ import { useContractTable } from "@contractspec/lib.presentation-runtime-react";
687
+ import { Badge } from "@contractspec/lib.ui-kit-web/ui/badge";
688
+ import { HStack, VStack } from "@contractspec/lib.ui-kit-web/ui/stack";
689
+ import { Text } from "@contractspec/lib.ui-kit-web/ui/text";
685
690
  import { jsxDEV as jsxDEV2 } from "react/jsx-dev-runtime";
686
691
  "use client";
687
692
  var QUERY_TYPE_COLORS = {
688
- SQL: "bg-blue-100 text-blue-700 dark:bg-blue-900/30 dark:text-blue-400",
689
- METRIC: "bg-purple-100 text-purple-700 dark:bg-purple-900/30 dark:text-purple-400",
690
- AGGREGATION: "bg-indigo-100 text-indigo-700 dark:bg-indigo-900/30 dark:text-indigo-400",
691
- CUSTOM: "bg-gray-100 text-gray-700 dark:bg-gray-900/30 dark:text-gray-400"
693
+ SQL: "default",
694
+ METRIC: "secondary",
695
+ AGGREGATION: "secondary",
696
+ CUSTOM: "outline"
692
697
  };
698
+ function formatJson(value) {
699
+ return JSON.stringify(value, null, 2);
700
+ }
693
701
  function AnalyticsQueriesTable({ queries }) {
694
- return /* @__PURE__ */ jsxDEV2("div", {
695
- className: "rounded-lg border border-border",
696
- children: /* @__PURE__ */ jsxDEV2("table", {
697
- className: "w-full",
698
- children: [
699
- /* @__PURE__ */ jsxDEV2("thead", {
700
- className: "border-border border-b bg-muted/30",
701
- children: /* @__PURE__ */ jsxDEV2("tr", {
702
- children: [
703
- /* @__PURE__ */ jsxDEV2("th", {
704
- className: "px-4 py-3 text-left font-medium text-sm",
705
- children: "Query"
706
- }, undefined, false, undefined, this),
707
- /* @__PURE__ */ jsxDEV2("th", {
708
- className: "px-4 py-3 text-left font-medium text-sm",
709
- children: "Type"
710
- }, undefined, false, undefined, this),
711
- /* @__PURE__ */ jsxDEV2("th", {
712
- className: "px-4 py-3 text-left font-medium text-sm",
713
- children: "Cache TTL"
714
- }, undefined, false, undefined, this),
715
- /* @__PURE__ */ jsxDEV2("th", {
716
- className: "px-4 py-3 text-left font-medium text-sm",
717
- children: "Shared"
718
- }, undefined, false, undefined, this)
719
- ]
720
- }, undefined, true, undefined, this)
721
- }, undefined, false, undefined, this),
722
- /* @__PURE__ */ jsxDEV2("tbody", {
723
- className: "divide-y divide-border",
702
+ const controller = useContractTable({
703
+ data: queries,
704
+ columns: [
705
+ {
706
+ id: "query",
707
+ header: "Query",
708
+ label: "Query",
709
+ accessor: (query) => query.name,
710
+ cell: ({ item }) => /* @__PURE__ */ jsxDEV2(VStack, {
711
+ gap: "xs",
724
712
  children: [
725
- queries.map((query) => /* @__PURE__ */ jsxDEV2("tr", {
726
- className: "hover:bg-muted/50",
713
+ /* @__PURE__ */ jsxDEV2(Text, {
714
+ className: "font-medium text-sm",
715
+ children: item.name
716
+ }, undefined, false, undefined, this),
717
+ /* @__PURE__ */ jsxDEV2(Text, {
718
+ className: "text-muted-foreground text-xs",
727
719
  children: [
728
- /* @__PURE__ */ jsxDEV2("td", {
729
- className: "px-4 py-3",
730
- children: [
731
- /* @__PURE__ */ jsxDEV2("div", {
732
- className: "font-medium",
733
- children: query.name
734
- }, undefined, false, undefined, this),
735
- /* @__PURE__ */ jsxDEV2("div", {
736
- className: "text-muted-foreground text-sm",
737
- children: query.description
738
- }, undefined, false, undefined, this)
739
- ]
740
- }, undefined, true, undefined, this),
741
- /* @__PURE__ */ jsxDEV2("td", {
742
- className: "px-4 py-3",
743
- children: /* @__PURE__ */ jsxDEV2("span", {
744
- className: `inline-flex rounded-full px-2 py-0.5 font-medium text-xs ${QUERY_TYPE_COLORS[query.type] ?? ""}`,
745
- children: query.type
746
- }, undefined, false, undefined, this)
747
- }, undefined, false, undefined, this),
748
- /* @__PURE__ */ jsxDEV2("td", {
749
- className: "px-4 py-3 text-muted-foreground text-sm",
750
- children: [
751
- query.cacheTtlSeconds,
752
- "s"
753
- ]
754
- }, undefined, true, undefined, this),
755
- /* @__PURE__ */ jsxDEV2("td", {
756
- className: "px-4 py-3",
757
- children: query.isShared ? /* @__PURE__ */ jsxDEV2("span", {
758
- className: "text-green-600 dark:text-green-400",
759
- children: "✓"
760
- }, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV2("span", {
761
- className: "text-muted-foreground",
762
- children: "—"
763
- }, undefined, false, undefined, this)
764
- }, undefined, false, undefined, this)
720
+ "Updated ",
721
+ item.updatedAt.toLocaleDateString()
765
722
  ]
766
- }, query.id, true, undefined, this)),
767
- queries.length === 0 && /* @__PURE__ */ jsxDEV2("tr", {
768
- children: /* @__PURE__ */ jsxDEV2("td", {
769
- colSpan: 4,
770
- className: "px-4 py-8 text-center text-muted-foreground",
771
- children: "No queries saved"
772
- }, undefined, false, undefined, this)
723
+ }, undefined, true, undefined, this)
724
+ ]
725
+ }, undefined, true, undefined, this),
726
+ size: 240,
727
+ minSize: 180,
728
+ canSort: true,
729
+ canPin: true,
730
+ canResize: true
731
+ },
732
+ {
733
+ id: "description",
734
+ header: "Description",
735
+ label: "Description",
736
+ accessor: (query) => query.description ?? "",
737
+ cell: ({ value }) => /* @__PURE__ */ jsxDEV2(Text, {
738
+ className: "line-clamp-2 text-muted-foreground text-sm",
739
+ children: String(value || "No description")
740
+ }, undefined, false, undefined, this),
741
+ size: 300,
742
+ minSize: 220,
743
+ canSort: false,
744
+ canHide: true,
745
+ canResize: true
746
+ },
747
+ {
748
+ id: "type",
749
+ header: "Type",
750
+ label: "Type",
751
+ accessorKey: "type",
752
+ cell: ({ value }) => /* @__PURE__ */ jsxDEV2(Badge, {
753
+ variant: QUERY_TYPE_COLORS[String(value)],
754
+ children: String(value)
755
+ }, undefined, false, undefined, this),
756
+ size: 150,
757
+ canSort: true,
758
+ canHide: true,
759
+ canResize: true
760
+ },
761
+ {
762
+ id: "cacheTtlSeconds",
763
+ header: "Cache TTL",
764
+ label: "Cache TTL",
765
+ accessorKey: "cacheTtlSeconds",
766
+ cell: ({ value }) => `${String(value)}s`,
767
+ align: "right",
768
+ size: 140,
769
+ canSort: true,
770
+ canResize: true
771
+ },
772
+ {
773
+ id: "isShared",
774
+ header: "Shared",
775
+ label: "Shared",
776
+ accessorKey: "isShared",
777
+ cell: ({ value }) => /* @__PURE__ */ jsxDEV2(Badge, {
778
+ variant: value ? "default" : "outline",
779
+ children: value ? "Shared" : "Private"
780
+ }, undefined, false, undefined, this),
781
+ size: 140,
782
+ canSort: true,
783
+ canHide: true,
784
+ canResize: true
785
+ }
786
+ ],
787
+ initialState: {
788
+ pagination: { pageIndex: 0, pageSize: 3 },
789
+ columnVisibility: { description: false },
790
+ columnPinning: { left: ["query"], right: [] }
791
+ },
792
+ renderExpandedContent: (query) => /* @__PURE__ */ jsxDEV2(VStack, {
793
+ gap: "sm",
794
+ className: "py-2",
795
+ children: [
796
+ /* @__PURE__ */ jsxDEV2(VStack, {
797
+ gap: "xs",
798
+ children: [
799
+ /* @__PURE__ */ jsxDEV2(Text, {
800
+ className: "font-medium text-sm",
801
+ children: "Description"
802
+ }, undefined, false, undefined, this),
803
+ /* @__PURE__ */ jsxDEV2(Text, {
804
+ className: "text-muted-foreground text-sm",
805
+ children: query.description ?? "No description"
806
+ }, undefined, false, undefined, this)
807
+ ]
808
+ }, undefined, true, undefined, this),
809
+ query.sql ? /* @__PURE__ */ jsxDEV2(VStack, {
810
+ gap: "xs",
811
+ children: [
812
+ /* @__PURE__ */ jsxDEV2(Text, {
813
+ className: "font-medium text-sm",
814
+ children: "SQL"
815
+ }, undefined, false, undefined, this),
816
+ /* @__PURE__ */ jsxDEV2("pre", {
817
+ className: "overflow-auto rounded-md bg-muted/40 p-3 text-xs",
818
+ children: query.sql
773
819
  }, undefined, false, undefined, this)
774
820
  ]
821
+ }, undefined, true, undefined, this) : null,
822
+ /* @__PURE__ */ jsxDEV2(VStack, {
823
+ gap: "xs",
824
+ children: [
825
+ /* @__PURE__ */ jsxDEV2(Text, {
826
+ className: "font-medium text-sm",
827
+ children: "Definition"
828
+ }, undefined, false, undefined, this),
829
+ /* @__PURE__ */ jsxDEV2("pre", {
830
+ className: "overflow-auto rounded-md bg-muted/40 p-3 text-xs",
831
+ children: formatJson(query.definition)
832
+ }, undefined, false, undefined, this)
833
+ ]
834
+ }, undefined, true, undefined, this)
835
+ ]
836
+ }, undefined, true, undefined, this),
837
+ getCanExpand: () => true
838
+ });
839
+ return /* @__PURE__ */ jsxDEV2(DataTable, {
840
+ controller,
841
+ title: "Saved Queries",
842
+ description: "Client-mode table using the shared ContractSpec controller and renderer.",
843
+ toolbar: /* @__PURE__ */ jsxDEV2(HStack, {
844
+ gap: "sm",
845
+ className: "flex-wrap",
846
+ children: [
847
+ /* @__PURE__ */ jsxDEV2(Text, {
848
+ className: "text-muted-foreground text-sm",
849
+ children: [
850
+ queries.length,
851
+ " queries"
852
+ ]
853
+ }, undefined, true, undefined, this),
854
+ /* @__PURE__ */ jsxDEV2(Text, {
855
+ className: "text-muted-foreground text-sm",
856
+ children: [
857
+ queries.filter((query) => query.isShared).length,
858
+ " shared"
859
+ ]
775
860
  }, undefined, true, undefined, this)
776
861
  ]
777
- }, undefined, true, undefined, this)
862
+ }, undefined, true, undefined, this),
863
+ emptyState: /* @__PURE__ */ jsxDEV2("div", {
864
+ className: "rounded-md border border-dashed p-8 text-center text-muted-foreground text-sm",
865
+ children: "No queries saved"
866
+ }, undefined, false, undefined, this)
778
867
  }, undefined, false, undefined, this);
779
868
  }
780
869
 
@@ -683,99 +683,188 @@ function gridSpanClass(gridWidth) {
683
683
  }
684
684
 
685
685
  // src/ui/AnalyticsQueriesTable.tsx
686
+ import { DataTable } from "@contractspec/lib.design-system";
687
+ import { useContractTable } from "@contractspec/lib.presentation-runtime-react";
688
+ import { Badge } from "@contractspec/lib.ui-kit-web/ui/badge";
689
+ import { HStack, VStack } from "@contractspec/lib.ui-kit-web/ui/stack";
690
+ import { Text } from "@contractspec/lib.ui-kit-web/ui/text";
686
691
  import { jsxDEV as jsxDEV2 } from "react/jsx-dev-runtime";
687
692
  "use client";
688
693
  var QUERY_TYPE_COLORS = {
689
- SQL: "bg-blue-100 text-blue-700 dark:bg-blue-900/30 dark:text-blue-400",
690
- METRIC: "bg-purple-100 text-purple-700 dark:bg-purple-900/30 dark:text-purple-400",
691
- AGGREGATION: "bg-indigo-100 text-indigo-700 dark:bg-indigo-900/30 dark:text-indigo-400",
692
- CUSTOM: "bg-gray-100 text-gray-700 dark:bg-gray-900/30 dark:text-gray-400"
694
+ SQL: "default",
695
+ METRIC: "secondary",
696
+ AGGREGATION: "secondary",
697
+ CUSTOM: "outline"
693
698
  };
699
+ function formatJson(value) {
700
+ return JSON.stringify(value, null, 2);
701
+ }
694
702
  function AnalyticsQueriesTable({ queries }) {
695
- return /* @__PURE__ */ jsxDEV2("div", {
696
- className: "rounded-lg border border-border",
697
- children: /* @__PURE__ */ jsxDEV2("table", {
698
- className: "w-full",
699
- children: [
700
- /* @__PURE__ */ jsxDEV2("thead", {
701
- className: "border-border border-b bg-muted/30",
702
- children: /* @__PURE__ */ jsxDEV2("tr", {
703
- children: [
704
- /* @__PURE__ */ jsxDEV2("th", {
705
- className: "px-4 py-3 text-left font-medium text-sm",
706
- children: "Query"
707
- }, undefined, false, undefined, this),
708
- /* @__PURE__ */ jsxDEV2("th", {
709
- className: "px-4 py-3 text-left font-medium text-sm",
710
- children: "Type"
711
- }, undefined, false, undefined, this),
712
- /* @__PURE__ */ jsxDEV2("th", {
713
- className: "px-4 py-3 text-left font-medium text-sm",
714
- children: "Cache TTL"
715
- }, undefined, false, undefined, this),
716
- /* @__PURE__ */ jsxDEV2("th", {
717
- className: "px-4 py-3 text-left font-medium text-sm",
718
- children: "Shared"
719
- }, undefined, false, undefined, this)
720
- ]
721
- }, undefined, true, undefined, this)
722
- }, undefined, false, undefined, this),
723
- /* @__PURE__ */ jsxDEV2("tbody", {
724
- className: "divide-y divide-border",
703
+ const controller = useContractTable({
704
+ data: queries,
705
+ columns: [
706
+ {
707
+ id: "query",
708
+ header: "Query",
709
+ label: "Query",
710
+ accessor: (query) => query.name,
711
+ cell: ({ item }) => /* @__PURE__ */ jsxDEV2(VStack, {
712
+ gap: "xs",
725
713
  children: [
726
- queries.map((query) => /* @__PURE__ */ jsxDEV2("tr", {
727
- className: "hover:bg-muted/50",
714
+ /* @__PURE__ */ jsxDEV2(Text, {
715
+ className: "font-medium text-sm",
716
+ children: item.name
717
+ }, undefined, false, undefined, this),
718
+ /* @__PURE__ */ jsxDEV2(Text, {
719
+ className: "text-muted-foreground text-xs",
728
720
  children: [
729
- /* @__PURE__ */ jsxDEV2("td", {
730
- className: "px-4 py-3",
731
- children: [
732
- /* @__PURE__ */ jsxDEV2("div", {
733
- className: "font-medium",
734
- children: query.name
735
- }, undefined, false, undefined, this),
736
- /* @__PURE__ */ jsxDEV2("div", {
737
- className: "text-muted-foreground text-sm",
738
- children: query.description
739
- }, undefined, false, undefined, this)
740
- ]
741
- }, undefined, true, undefined, this),
742
- /* @__PURE__ */ jsxDEV2("td", {
743
- className: "px-4 py-3",
744
- children: /* @__PURE__ */ jsxDEV2("span", {
745
- className: `inline-flex rounded-full px-2 py-0.5 font-medium text-xs ${QUERY_TYPE_COLORS[query.type] ?? ""}`,
746
- children: query.type
747
- }, undefined, false, undefined, this)
748
- }, undefined, false, undefined, this),
749
- /* @__PURE__ */ jsxDEV2("td", {
750
- className: "px-4 py-3 text-muted-foreground text-sm",
751
- children: [
752
- query.cacheTtlSeconds,
753
- "s"
754
- ]
755
- }, undefined, true, undefined, this),
756
- /* @__PURE__ */ jsxDEV2("td", {
757
- className: "px-4 py-3",
758
- children: query.isShared ? /* @__PURE__ */ jsxDEV2("span", {
759
- className: "text-green-600 dark:text-green-400",
760
- children: "\u2713"
761
- }, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV2("span", {
762
- className: "text-muted-foreground",
763
- children: "\u2014"
764
- }, undefined, false, undefined, this)
765
- }, undefined, false, undefined, this)
721
+ "Updated ",
722
+ item.updatedAt.toLocaleDateString()
766
723
  ]
767
- }, query.id, true, undefined, this)),
768
- queries.length === 0 && /* @__PURE__ */ jsxDEV2("tr", {
769
- children: /* @__PURE__ */ jsxDEV2("td", {
770
- colSpan: 4,
771
- className: "px-4 py-8 text-center text-muted-foreground",
772
- children: "No queries saved"
773
- }, undefined, false, undefined, this)
724
+ }, undefined, true, undefined, this)
725
+ ]
726
+ }, undefined, true, undefined, this),
727
+ size: 240,
728
+ minSize: 180,
729
+ canSort: true,
730
+ canPin: true,
731
+ canResize: true
732
+ },
733
+ {
734
+ id: "description",
735
+ header: "Description",
736
+ label: "Description",
737
+ accessor: (query) => query.description ?? "",
738
+ cell: ({ value }) => /* @__PURE__ */ jsxDEV2(Text, {
739
+ className: "line-clamp-2 text-muted-foreground text-sm",
740
+ children: String(value || "No description")
741
+ }, undefined, false, undefined, this),
742
+ size: 300,
743
+ minSize: 220,
744
+ canSort: false,
745
+ canHide: true,
746
+ canResize: true
747
+ },
748
+ {
749
+ id: "type",
750
+ header: "Type",
751
+ label: "Type",
752
+ accessorKey: "type",
753
+ cell: ({ value }) => /* @__PURE__ */ jsxDEV2(Badge, {
754
+ variant: QUERY_TYPE_COLORS[String(value)],
755
+ children: String(value)
756
+ }, undefined, false, undefined, this),
757
+ size: 150,
758
+ canSort: true,
759
+ canHide: true,
760
+ canResize: true
761
+ },
762
+ {
763
+ id: "cacheTtlSeconds",
764
+ header: "Cache TTL",
765
+ label: "Cache TTL",
766
+ accessorKey: "cacheTtlSeconds",
767
+ cell: ({ value }) => `${String(value)}s`,
768
+ align: "right",
769
+ size: 140,
770
+ canSort: true,
771
+ canResize: true
772
+ },
773
+ {
774
+ id: "isShared",
775
+ header: "Shared",
776
+ label: "Shared",
777
+ accessorKey: "isShared",
778
+ cell: ({ value }) => /* @__PURE__ */ jsxDEV2(Badge, {
779
+ variant: value ? "default" : "outline",
780
+ children: value ? "Shared" : "Private"
781
+ }, undefined, false, undefined, this),
782
+ size: 140,
783
+ canSort: true,
784
+ canHide: true,
785
+ canResize: true
786
+ }
787
+ ],
788
+ initialState: {
789
+ pagination: { pageIndex: 0, pageSize: 3 },
790
+ columnVisibility: { description: false },
791
+ columnPinning: { left: ["query"], right: [] }
792
+ },
793
+ renderExpandedContent: (query) => /* @__PURE__ */ jsxDEV2(VStack, {
794
+ gap: "sm",
795
+ className: "py-2",
796
+ children: [
797
+ /* @__PURE__ */ jsxDEV2(VStack, {
798
+ gap: "xs",
799
+ children: [
800
+ /* @__PURE__ */ jsxDEV2(Text, {
801
+ className: "font-medium text-sm",
802
+ children: "Description"
803
+ }, undefined, false, undefined, this),
804
+ /* @__PURE__ */ jsxDEV2(Text, {
805
+ className: "text-muted-foreground text-sm",
806
+ children: query.description ?? "No description"
807
+ }, undefined, false, undefined, this)
808
+ ]
809
+ }, undefined, true, undefined, this),
810
+ query.sql ? /* @__PURE__ */ jsxDEV2(VStack, {
811
+ gap: "xs",
812
+ children: [
813
+ /* @__PURE__ */ jsxDEV2(Text, {
814
+ className: "font-medium text-sm",
815
+ children: "SQL"
816
+ }, undefined, false, undefined, this),
817
+ /* @__PURE__ */ jsxDEV2("pre", {
818
+ className: "overflow-auto rounded-md bg-muted/40 p-3 text-xs",
819
+ children: query.sql
774
820
  }, undefined, false, undefined, this)
775
821
  ]
822
+ }, undefined, true, undefined, this) : null,
823
+ /* @__PURE__ */ jsxDEV2(VStack, {
824
+ gap: "xs",
825
+ children: [
826
+ /* @__PURE__ */ jsxDEV2(Text, {
827
+ className: "font-medium text-sm",
828
+ children: "Definition"
829
+ }, undefined, false, undefined, this),
830
+ /* @__PURE__ */ jsxDEV2("pre", {
831
+ className: "overflow-auto rounded-md bg-muted/40 p-3 text-xs",
832
+ children: formatJson(query.definition)
833
+ }, undefined, false, undefined, this)
834
+ ]
835
+ }, undefined, true, undefined, this)
836
+ ]
837
+ }, undefined, true, undefined, this),
838
+ getCanExpand: () => true
839
+ });
840
+ return /* @__PURE__ */ jsxDEV2(DataTable, {
841
+ controller,
842
+ title: "Saved Queries",
843
+ description: "Client-mode table using the shared ContractSpec controller and renderer.",
844
+ toolbar: /* @__PURE__ */ jsxDEV2(HStack, {
845
+ gap: "sm",
846
+ className: "flex-wrap",
847
+ children: [
848
+ /* @__PURE__ */ jsxDEV2(Text, {
849
+ className: "text-muted-foreground text-sm",
850
+ children: [
851
+ queries.length,
852
+ " queries"
853
+ ]
854
+ }, undefined, true, undefined, this),
855
+ /* @__PURE__ */ jsxDEV2(Text, {
856
+ className: "text-muted-foreground text-sm",
857
+ children: [
858
+ queries.filter((query) => query.isShared).length,
859
+ " shared"
860
+ ]
776
861
  }, undefined, true, undefined, this)
777
862
  ]
778
- }, undefined, true, undefined, this)
863
+ }, undefined, true, undefined, this),
864
+ emptyState: /* @__PURE__ */ jsxDEV2("div", {
865
+ className: "rounded-md border border-dashed p-8 text-center text-muted-foreground text-sm",
866
+ children: "No queries saved"
867
+ }, undefined, false, undefined, this)
779
868
  }, undefined, false, undefined, this);
780
869
  }
781
870