@contractspec/example.saas-boilerplate 3.7.7 → 3.8.4

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.
Files changed (52) hide show
  1. package/.turbo/turbo-build.log +36 -24
  2. package/CHANGELOG.md +72 -0
  3. package/README.md +1 -0
  4. package/dist/browser/index.js +371 -92
  5. package/dist/browser/saas-boilerplate.feature.js +208 -0
  6. package/dist/browser/ui/SaasDashboard.js +311 -60
  7. package/dist/browser/ui/SaasDashboard.visualizations.js +249 -0
  8. package/dist/browser/ui/index.js +362 -92
  9. package/dist/browser/ui/renderers/index.js +229 -3
  10. package/dist/browser/ui/renderers/project-list.markdown.js +229 -3
  11. package/dist/browser/visualizations/catalog.js +155 -0
  12. package/dist/browser/visualizations/index.js +217 -0
  13. package/dist/browser/visualizations/selectors.js +210 -0
  14. package/dist/index.d.ts +1 -0
  15. package/dist/index.js +371 -92
  16. package/dist/node/index.js +371 -92
  17. package/dist/node/saas-boilerplate.feature.js +208 -0
  18. package/dist/node/ui/SaasDashboard.js +311 -60
  19. package/dist/node/ui/SaasDashboard.visualizations.js +249 -0
  20. package/dist/node/ui/index.js +362 -92
  21. package/dist/node/ui/renderers/index.js +229 -3
  22. package/dist/node/ui/renderers/project-list.markdown.js +229 -3
  23. package/dist/node/visualizations/catalog.js +155 -0
  24. package/dist/node/visualizations/index.js +217 -0
  25. package/dist/node/visualizations/selectors.js +210 -0
  26. package/dist/saas-boilerplate.feature.js +208 -0
  27. package/dist/ui/SaasDashboard.js +311 -60
  28. package/dist/ui/SaasDashboard.visualizations.d.ts +5 -0
  29. package/dist/ui/SaasDashboard.visualizations.js +250 -0
  30. package/dist/ui/index.js +362 -92
  31. package/dist/ui/renderers/index.js +229 -3
  32. package/dist/ui/renderers/project-list.markdown.d.ts +1 -1
  33. package/dist/ui/renderers/project-list.markdown.js +229 -3
  34. package/dist/ui/renderers/project-list.renderer.d.ts +1 -1
  35. package/dist/visualizations/catalog.d.ts +11 -0
  36. package/dist/visualizations/catalog.js +156 -0
  37. package/dist/visualizations/index.d.ts +2 -0
  38. package/dist/visualizations/index.js +218 -0
  39. package/dist/visualizations/selectors.d.ts +8 -0
  40. package/dist/visualizations/selectors.js +211 -0
  41. package/dist/visualizations/selectors.test.d.ts +1 -0
  42. package/package.json +70 -13
  43. package/src/index.ts +1 -0
  44. package/src/saas-boilerplate.feature.ts +3 -0
  45. package/src/ui/SaasDashboard.tsx +8 -0
  46. package/src/ui/SaasDashboard.visualizations.tsx +41 -0
  47. package/src/ui/renderers/project-list.markdown.ts +39 -15
  48. package/src/ui/renderers/project-list.renderer.tsx +1 -1
  49. package/src/visualizations/catalog.ts +153 -0
  50. package/src/visualizations/index.ts +2 -0
  51. package/src/visualizations/selectors.test.ts +25 -0
  52. package/src/visualizations/selectors.ts +85 -0
@@ -1,4 +1,211 @@
1
1
  // @bun
2
+ // src/visualizations/catalog.ts
3
+ import {
4
+ defineVisualization,
5
+ VisualizationRegistry
6
+ } from "@contractspec/lib.contracts-spec/visualizations";
7
+ var PROJECT_LIST_REF = {
8
+ key: "saas.project.list",
9
+ version: "1.0.0"
10
+ };
11
+ var META = {
12
+ version: "1.0.0",
13
+ domain: "saas",
14
+ stability: "experimental",
15
+ owners: ["@example.saas-boilerplate"],
16
+ tags: ["saas", "visualization", "projects"]
17
+ };
18
+ var SaasProjectUsageVisualization = defineVisualization({
19
+ meta: {
20
+ ...META,
21
+ key: "saas-boilerplate.visualization.project-usage",
22
+ title: "Project Capacity",
23
+ description: "Current project count against the current plan limit.",
24
+ goal: "Show usage against the active plan allowance.",
25
+ context: "SaaS account overview."
26
+ },
27
+ source: { primary: PROJECT_LIST_REF, resultPath: "data" },
28
+ visualization: {
29
+ kind: "metric",
30
+ measure: "totalProjects",
31
+ comparisonMeasure: "projectLimit",
32
+ measures: [
33
+ {
34
+ key: "totalProjects",
35
+ label: "Projects",
36
+ dataPath: "totalProjects",
37
+ format: "number"
38
+ },
39
+ {
40
+ key: "projectLimit",
41
+ label: "Plan Limit",
42
+ dataPath: "projectLimit",
43
+ format: "number"
44
+ }
45
+ ],
46
+ table: { caption: "Current project count and plan limit." }
47
+ }
48
+ });
49
+ var SaasProjectStatusVisualization = defineVisualization({
50
+ meta: {
51
+ ...META,
52
+ key: "saas-boilerplate.visualization.project-status",
53
+ title: "Project Status",
54
+ description: "Distribution of project states.",
55
+ goal: "Show the mix of active, draft, and archived projects.",
56
+ context: "Project portfolio overview."
57
+ },
58
+ source: { primary: PROJECT_LIST_REF, resultPath: "data" },
59
+ visualization: {
60
+ kind: "pie",
61
+ nameDimension: "status",
62
+ valueMeasure: "projects",
63
+ dimensions: [
64
+ { key: "status", label: "Status", dataPath: "status", type: "category" }
65
+ ],
66
+ measures: [
67
+ {
68
+ key: "projects",
69
+ label: "Projects",
70
+ dataPath: "projects",
71
+ format: "number"
72
+ }
73
+ ],
74
+ table: { caption: "Project counts by status." }
75
+ }
76
+ });
77
+ var SaasProjectTierVisualization = defineVisualization({
78
+ meta: {
79
+ ...META,
80
+ key: "saas-boilerplate.visualization.project-tiers",
81
+ title: "Tier Comparison",
82
+ description: "Distribution of projects across tiers.",
83
+ goal: "Compare how the current portfolio is distributed by tier.",
84
+ context: "Plan and packaging overview."
85
+ },
86
+ source: { primary: PROJECT_LIST_REF, resultPath: "data" },
87
+ visualization: {
88
+ kind: "cartesian",
89
+ variant: "bar",
90
+ xDimension: "tier",
91
+ yMeasures: ["projects"],
92
+ dimensions: [
93
+ { key: "tier", label: "Tier", dataPath: "tier", type: "category" }
94
+ ],
95
+ measures: [
96
+ {
97
+ key: "projects",
98
+ label: "Projects",
99
+ dataPath: "projects",
100
+ format: "number",
101
+ color: "#1d4ed8"
102
+ }
103
+ ],
104
+ table: { caption: "Project counts by tier." }
105
+ }
106
+ });
107
+ var SaasProjectActivityVisualization = defineVisualization({
108
+ meta: {
109
+ ...META,
110
+ key: "saas-boilerplate.visualization.project-activity",
111
+ title: "Recent Project Activity",
112
+ description: "Daily project creation activity.",
113
+ goal: "Show recent project activity over time.",
114
+ context: "Project portfolio trend view."
115
+ },
116
+ source: { primary: PROJECT_LIST_REF, resultPath: "data" },
117
+ visualization: {
118
+ kind: "cartesian",
119
+ variant: "line",
120
+ xDimension: "day",
121
+ yMeasures: ["projects"],
122
+ dimensions: [{ key: "day", label: "Day", dataPath: "day", type: "time" }],
123
+ measures: [
124
+ {
125
+ key: "projects",
126
+ label: "Projects",
127
+ dataPath: "projects",
128
+ format: "number",
129
+ color: "#0f766e"
130
+ }
131
+ ],
132
+ table: { caption: "Daily project creation counts." }
133
+ }
134
+ });
135
+ var SaasVisualizationSpecs = [
136
+ SaasProjectUsageVisualization,
137
+ SaasProjectStatusVisualization,
138
+ SaasProjectTierVisualization,
139
+ SaasProjectActivityVisualization
140
+ ];
141
+ var SaasVisualizationRegistry = new VisualizationRegistry([
142
+ ...SaasVisualizationSpecs
143
+ ]);
144
+ var SaasVisualizationRefs = SaasVisualizationSpecs.map((spec) => ({
145
+ key: spec.meta.key,
146
+ version: spec.meta.version
147
+ }));
148
+
149
+ // src/visualizations/selectors.ts
150
+ function toDayKey(value) {
151
+ const date = value instanceof Date ? value : new Date(value);
152
+ return date.toISOString().slice(0, 10);
153
+ }
154
+ function createSaasVisualizationItems(projects, projectLimit = 10) {
155
+ const statusCounts = new Map;
156
+ const tierCounts = new Map;
157
+ const activityCounts = new Map;
158
+ for (const project of projects) {
159
+ statusCounts.set(project.status, (statusCounts.get(project.status) ?? 0) + 1);
160
+ tierCounts.set(project.tier, (tierCounts.get(project.tier) ?? 0) + 1);
161
+ const day = toDayKey(project.createdAt);
162
+ activityCounts.set(day, (activityCounts.get(day) ?? 0) + 1);
163
+ }
164
+ return [
165
+ {
166
+ key: "saas-capacity",
167
+ spec: SaasProjectUsageVisualization,
168
+ data: { data: [{ totalProjects: projects.length, projectLimit }] },
169
+ title: "Project Capacity",
170
+ description: "Current project count compared to the active limit.",
171
+ height: 220
172
+ },
173
+ {
174
+ key: "saas-status",
175
+ spec: SaasProjectStatusVisualization,
176
+ data: {
177
+ data: Array.from(statusCounts.entries()).map(([status, count]) => ({
178
+ status,
179
+ projects: count
180
+ }))
181
+ },
182
+ title: "Project Status",
183
+ description: "Status mix across the current project portfolio.",
184
+ height: 260
185
+ },
186
+ {
187
+ key: "saas-tier",
188
+ spec: SaasProjectTierVisualization,
189
+ data: {
190
+ data: Array.from(tierCounts.entries()).map(([tier, count]) => ({
191
+ tier,
192
+ projects: count
193
+ }))
194
+ },
195
+ title: "Tier Comparison",
196
+ description: "How projects are distributed across tiers."
197
+ },
198
+ {
199
+ key: "saas-activity",
200
+ spec: SaasProjectActivityVisualization,
201
+ data: {
202
+ data: Array.from(activityCounts.entries()).sort(([left], [right]) => left.localeCompare(right)).map(([day, count]) => ({ day, projects: count }))
203
+ },
204
+ title: "Recent Project Activity",
205
+ description: "Daily project creation activity."
206
+ }
207
+ ];
208
+ }
2
209
  // src/ui/hooks/useProjectList.ts
3
210
  import { useTemplateRuntime } from "@contractspec/lib.example-shared-ui";
4
211
  import { useCallback, useEffect, useMemo, useState } from "react";
@@ -636,6 +843,46 @@ function ProjectActionsModal({
636
843
  }, undefined, true, undefined, this);
637
844
  }
638
845
 
846
+ // src/ui/SaasDashboard.visualizations.tsx
847
+ import {
848
+ VisualizationCard,
849
+ VisualizationGrid
850
+ } from "@contractspec/lib.design-system";
851
+ import { jsxDEV as jsxDEV3 } from "react/jsx-dev-runtime";
852
+ "use client";
853
+ function SaasVisualizationOverview({
854
+ projects,
855
+ projectLimit
856
+ }) {
857
+ const items = createSaasVisualizationItems(projects, projectLimit);
858
+ return /* @__PURE__ */ jsxDEV3("section", {
859
+ className: "space-y-3",
860
+ children: [
861
+ /* @__PURE__ */ jsxDEV3("div", {
862
+ children: [
863
+ /* @__PURE__ */ jsxDEV3("h3", {
864
+ className: "font-semibold text-lg",
865
+ children: "Portfolio Visualizations"
866
+ }, undefined, false, undefined, this),
867
+ /* @__PURE__ */ jsxDEV3("p", {
868
+ className: "text-muted-foreground text-sm",
869
+ children: "Contract-backed charts for project mix, capacity, and activity."
870
+ }, undefined, false, undefined, this)
871
+ ]
872
+ }, undefined, true, undefined, this),
873
+ /* @__PURE__ */ jsxDEV3(VisualizationGrid, {
874
+ children: items.map((item) => /* @__PURE__ */ jsxDEV3(VisualizationCard, {
875
+ data: item.data,
876
+ description: item.description,
877
+ height: item.height,
878
+ spec: item.spec,
879
+ title: item.title
880
+ }, item.key, false, undefined, this))
881
+ }, undefined, false, undefined, this)
882
+ ]
883
+ }, undefined, true, undefined, this);
884
+ }
885
+
639
886
  // src/ui/SaasDashboard.tsx
640
887
  import {
641
888
  Button as Button3,
@@ -648,7 +895,7 @@ import {
648
895
  StatusChip
649
896
  } from "@contractspec/lib.design-system";
650
897
  import { useCallback as useCallback3, useState as useState5 } from "react";
651
- import { jsxDEV as jsxDEV3 } from "react/jsx-dev-runtime";
898
+ import { jsxDEV as jsxDEV4 } from "react/jsx-dev-runtime";
652
899
  "use client";
653
900
  function getStatusTone(status) {
654
901
  switch (status) {
@@ -683,32 +930,32 @@ function SaasDashboard() {
683
930
  { id: "settings", label: "Settings", icon: "\u2699\uFE0F" }
684
931
  ];
685
932
  if (loading && !data) {
686
- return /* @__PURE__ */ jsxDEV3(LoaderBlock, {
933
+ return /* @__PURE__ */ jsxDEV4(LoaderBlock, {
687
934
  label: "Loading dashboard..."
688
935
  }, undefined, false, undefined, this);
689
936
  }
690
937
  if (error) {
691
- return /* @__PURE__ */ jsxDEV3(ErrorState, {
938
+ return /* @__PURE__ */ jsxDEV4(ErrorState, {
692
939
  title: "Failed to load dashboard",
693
940
  description: error.message,
694
941
  onRetry: refetch,
695
942
  retryLabel: "Retry"
696
943
  }, undefined, false, undefined, this);
697
944
  }
698
- return /* @__PURE__ */ jsxDEV3("div", {
945
+ return /* @__PURE__ */ jsxDEV4("div", {
699
946
  className: "space-y-6",
700
947
  children: [
701
- /* @__PURE__ */ jsxDEV3("div", {
948
+ /* @__PURE__ */ jsxDEV4("div", {
702
949
  className: "flex items-center justify-between",
703
950
  children: [
704
- /* @__PURE__ */ jsxDEV3("h2", {
951
+ /* @__PURE__ */ jsxDEV4("h2", {
705
952
  className: "font-bold text-2xl",
706
953
  children: "SaaS Dashboard"
707
954
  }, undefined, false, undefined, this),
708
- activeTab === "projects" && /* @__PURE__ */ jsxDEV3(Button3, {
955
+ activeTab === "projects" && /* @__PURE__ */ jsxDEV4(Button3, {
709
956
  onPress: () => setIsCreateModalOpen(true),
710
957
  children: [
711
- /* @__PURE__ */ jsxDEV3("span", {
958
+ /* @__PURE__ */ jsxDEV4("span", {
712
959
  className: "mr-2",
713
960
  children: "+"
714
961
  }, undefined, false, undefined, this),
@@ -717,59 +964,63 @@ function SaasDashboard() {
717
964
  }, undefined, true, undefined, this)
718
965
  ]
719
966
  }, undefined, true, undefined, this),
720
- stats && subscription && /* @__PURE__ */ jsxDEV3(StatCardGroup, {
967
+ stats && subscription && /* @__PURE__ */ jsxDEV4(StatCardGroup, {
721
968
  children: [
722
- /* @__PURE__ */ jsxDEV3(StatCard, {
969
+ /* @__PURE__ */ jsxDEV4(StatCard, {
723
970
  label: "Projects",
724
971
  value: stats.total.toString()
725
972
  }, undefined, false, undefined, this),
726
- /* @__PURE__ */ jsxDEV3(StatCard, {
973
+ /* @__PURE__ */ jsxDEV4(StatCard, {
727
974
  label: "Active",
728
975
  value: stats.activeCount.toString()
729
976
  }, undefined, false, undefined, this),
730
- /* @__PURE__ */ jsxDEV3(StatCard, {
977
+ /* @__PURE__ */ jsxDEV4(StatCard, {
731
978
  label: "Draft",
732
979
  value: stats.draftCount.toString()
733
980
  }, undefined, false, undefined, this),
734
- /* @__PURE__ */ jsxDEV3(StatCard, {
981
+ /* @__PURE__ */ jsxDEV4(StatCard, {
735
982
  label: "Plan",
736
983
  value: subscription.plan,
737
984
  hint: subscription.status
738
985
  }, undefined, false, undefined, this)
739
986
  ]
740
987
  }, undefined, true, undefined, this),
741
- /* @__PURE__ */ jsxDEV3("nav", {
988
+ data && stats && /* @__PURE__ */ jsxDEV4(SaasVisualizationOverview, {
989
+ projectLimit: stats.projectLimit,
990
+ projects: data.items
991
+ }, undefined, false, undefined, this),
992
+ /* @__PURE__ */ jsxDEV4("nav", {
742
993
  className: "flex gap-1 rounded-lg bg-muted p-1",
743
994
  role: "tablist",
744
- children: tabs.map((tab) => /* @__PURE__ */ jsxDEV3("button", {
995
+ children: tabs.map((tab) => /* @__PURE__ */ jsxDEV4("button", {
745
996
  type: "button",
746
997
  role: "tab",
747
998
  "aria-selected": activeTab === tab.id,
748
999
  onClick: () => setActiveTab(tab.id),
749
1000
  className: `flex flex-1 items-center justify-center gap-2 rounded-md px-4 py-2 font-medium text-sm transition-colors ${activeTab === tab.id ? "bg-background text-foreground shadow-sm" : "text-muted-foreground hover:text-foreground"}`,
750
1001
  children: [
751
- /* @__PURE__ */ jsxDEV3("span", {
1002
+ /* @__PURE__ */ jsxDEV4("span", {
752
1003
  children: tab.icon
753
1004
  }, undefined, false, undefined, this),
754
1005
  tab.label
755
1006
  ]
756
1007
  }, tab.id, true, undefined, this))
757
1008
  }, undefined, false, undefined, this),
758
- /* @__PURE__ */ jsxDEV3("div", {
1009
+ /* @__PURE__ */ jsxDEV4("div", {
759
1010
  className: "min-h-[400px]",
760
1011
  role: "tabpanel",
761
1012
  children: [
762
- activeTab === "projects" && /* @__PURE__ */ jsxDEV3(ProjectsTab, {
1013
+ activeTab === "projects" && /* @__PURE__ */ jsxDEV4(ProjectsTab, {
763
1014
  data,
764
1015
  onProjectClick: handleProjectClick
765
1016
  }, undefined, false, undefined, this),
766
- activeTab === "billing" && /* @__PURE__ */ jsxDEV3(BillingTab, {
1017
+ activeTab === "billing" && /* @__PURE__ */ jsxDEV4(BillingTab, {
767
1018
  subscription
768
1019
  }, undefined, false, undefined, this),
769
- activeTab === "settings" && /* @__PURE__ */ jsxDEV3(SettingsTab, {}, undefined, false, undefined, this)
1020
+ activeTab === "settings" && /* @__PURE__ */ jsxDEV4(SettingsTab, {}, undefined, false, undefined, this)
770
1021
  ]
771
1022
  }, undefined, true, undefined, this),
772
- /* @__PURE__ */ jsxDEV3(CreateProjectModal, {
1023
+ /* @__PURE__ */ jsxDEV4(CreateProjectModal, {
773
1024
  isOpen: isCreateModalOpen,
774
1025
  onClose: () => setIsCreateModalOpen(false),
775
1026
  onSubmit: async (input) => {
@@ -777,7 +1028,7 @@ function SaasDashboard() {
777
1028
  },
778
1029
  isLoading: mutations.createState.loading
779
1030
  }, undefined, false, undefined, this),
780
- /* @__PURE__ */ jsxDEV3(ProjectActionsModal, {
1031
+ /* @__PURE__ */ jsxDEV4(ProjectActionsModal, {
781
1032
  isOpen: isProjectActionsOpen,
782
1033
  project: selectedProject,
783
1034
  onClose: () => {
@@ -803,34 +1054,34 @@ function SaasDashboard() {
803
1054
  }
804
1055
  function ProjectsTab({ data, onProjectClick }) {
805
1056
  if (!data?.items.length) {
806
- return /* @__PURE__ */ jsxDEV3(EmptyState, {
1057
+ return /* @__PURE__ */ jsxDEV4(EmptyState, {
807
1058
  title: "No projects yet",
808
1059
  description: "Create your first project to get started."
809
1060
  }, undefined, false, undefined, this);
810
1061
  }
811
- return /* @__PURE__ */ jsxDEV3("div", {
1062
+ return /* @__PURE__ */ jsxDEV4("div", {
812
1063
  className: "space-y-4",
813
- children: /* @__PURE__ */ jsxDEV3("div", {
1064
+ children: /* @__PURE__ */ jsxDEV4("div", {
814
1065
  className: "grid gap-4 md:grid-cols-2 lg:grid-cols-3",
815
- children: data.items.map((project) => /* @__PURE__ */ jsxDEV3(EntityCard, {
1066
+ children: data.items.map((project) => /* @__PURE__ */ jsxDEV4(EntityCard, {
816
1067
  cardTitle: project.name,
817
1068
  cardSubtitle: project.tier,
818
- meta: /* @__PURE__ */ jsxDEV3("p", {
1069
+ meta: /* @__PURE__ */ jsxDEV4("p", {
819
1070
  className: "text-muted-foreground text-sm",
820
1071
  children: project.description
821
1072
  }, undefined, false, undefined, this),
822
- chips: /* @__PURE__ */ jsxDEV3(StatusChip, {
1073
+ chips: /* @__PURE__ */ jsxDEV4(StatusChip, {
823
1074
  tone: getStatusTone(project.status),
824
1075
  label: project.status
825
1076
  }, undefined, false, undefined, this),
826
- footer: /* @__PURE__ */ jsxDEV3("div", {
1077
+ footer: /* @__PURE__ */ jsxDEV4("div", {
827
1078
  className: "flex w-full items-center justify-between",
828
1079
  children: [
829
- /* @__PURE__ */ jsxDEV3("span", {
1080
+ /* @__PURE__ */ jsxDEV4("span", {
830
1081
  className: "text-muted-foreground text-xs",
831
1082
  children: project.updatedAt.toLocaleDateString()
832
1083
  }, undefined, false, undefined, this),
833
- /* @__PURE__ */ jsxDEV3(Button3, {
1084
+ /* @__PURE__ */ jsxDEV4(Button3, {
834
1085
  variant: "ghost",
835
1086
  size: "sm",
836
1087
  onPress: () => onProjectClick?.(project),
@@ -845,25 +1096,25 @@ function ProjectsTab({ data, onProjectClick }) {
845
1096
  function BillingTab({ subscription }) {
846
1097
  if (!subscription)
847
1098
  return null;
848
- return /* @__PURE__ */ jsxDEV3("div", {
1099
+ return /* @__PURE__ */ jsxDEV4("div", {
849
1100
  className: "space-y-6",
850
1101
  children: [
851
- /* @__PURE__ */ jsxDEV3("div", {
1102
+ /* @__PURE__ */ jsxDEV4("div", {
852
1103
  className: "rounded-xl border border-border bg-card p-6",
853
1104
  children: [
854
- /* @__PURE__ */ jsxDEV3("div", {
1105
+ /* @__PURE__ */ jsxDEV4("div", {
855
1106
  className: "flex items-start justify-between",
856
1107
  children: [
857
- /* @__PURE__ */ jsxDEV3("div", {
1108
+ /* @__PURE__ */ jsxDEV4("div", {
858
1109
  children: [
859
- /* @__PURE__ */ jsxDEV3("h3", {
1110
+ /* @__PURE__ */ jsxDEV4("h3", {
860
1111
  className: "font-semibold text-lg",
861
1112
  children: [
862
1113
  subscription.plan,
863
1114
  " Plan"
864
1115
  ]
865
1116
  }, undefined, true, undefined, this),
866
- /* @__PURE__ */ jsxDEV3("p", {
1117
+ /* @__PURE__ */ jsxDEV4("p", {
867
1118
  className: "text-muted-foreground text-sm",
868
1119
  children: [
869
1120
  "Current period:",
@@ -874,7 +1125,7 @@ function BillingTab({ subscription }) {
874
1125
  subscription.currentPeriodEnd.toLocaleDateString()
875
1126
  ]
876
1127
  }, undefined, true, undefined, this),
877
- /* @__PURE__ */ jsxDEV3("p", {
1128
+ /* @__PURE__ */ jsxDEV4("p", {
878
1129
  className: "text-muted-foreground text-sm",
879
1130
  children: [
880
1131
  "Billing cycle: ",
@@ -883,21 +1134,21 @@ function BillingTab({ subscription }) {
883
1134
  }, undefined, true, undefined, this)
884
1135
  ]
885
1136
  }, undefined, true, undefined, this),
886
- /* @__PURE__ */ jsxDEV3(StatusChip, {
1137
+ /* @__PURE__ */ jsxDEV4(StatusChip, {
887
1138
  tone: "success",
888
1139
  label: subscription.status
889
1140
  }, undefined, false, undefined, this)
890
1141
  ]
891
1142
  }, undefined, true, undefined, this),
892
- /* @__PURE__ */ jsxDEV3("div", {
1143
+ /* @__PURE__ */ jsxDEV4("div", {
893
1144
  className: "mt-4 flex gap-3",
894
1145
  children: [
895
- /* @__PURE__ */ jsxDEV3(Button3, {
1146
+ /* @__PURE__ */ jsxDEV4(Button3, {
896
1147
  variant: "outline",
897
1148
  onPress: () => alert("Upgrade clicked!"),
898
1149
  children: "Upgrade Plan"
899
1150
  }, undefined, false, undefined, this),
900
- /* @__PURE__ */ jsxDEV3(Button3, {
1151
+ /* @__PURE__ */ jsxDEV4(Button3, {
901
1152
  variant: "ghost",
902
1153
  onPress: () => alert("Manage Billing clicked!"),
903
1154
  children: "Manage Billing"
@@ -906,9 +1157,9 @@ function BillingTab({ subscription }) {
906
1157
  }, undefined, true, undefined, this)
907
1158
  ]
908
1159
  }, undefined, true, undefined, this),
909
- subscription.cancelAtPeriodEnd && /* @__PURE__ */ jsxDEV3("div", {
1160
+ subscription.cancelAtPeriodEnd && /* @__PURE__ */ jsxDEV4("div", {
910
1161
  className: "rounded-xl border border-border bg-destructive/10 p-4 text-destructive",
911
- children: /* @__PURE__ */ jsxDEV3("p", {
1162
+ children: /* @__PURE__ */ jsxDEV4("p", {
912
1163
  className: "font-medium text-sm",
913
1164
  children: "\u26A0\uFE0F Your subscription will be cancelled at the end of the current period."
914
1165
  }, undefined, false, undefined, this)
@@ -917,26 +1168,26 @@ function BillingTab({ subscription }) {
917
1168
  }, undefined, true, undefined, this);
918
1169
  }
919
1170
  function SettingsTab() {
920
- return /* @__PURE__ */ jsxDEV3("div", {
1171
+ return /* @__PURE__ */ jsxDEV4("div", {
921
1172
  className: "space-y-6",
922
- children: /* @__PURE__ */ jsxDEV3("div", {
1173
+ children: /* @__PURE__ */ jsxDEV4("div", {
923
1174
  className: "rounded-xl border border-border bg-card p-6",
924
1175
  children: [
925
- /* @__PURE__ */ jsxDEV3("h3", {
1176
+ /* @__PURE__ */ jsxDEV4("h3", {
926
1177
  className: "mb-4 font-semibold text-lg",
927
1178
  children: "Organization Settings"
928
1179
  }, undefined, false, undefined, this),
929
- /* @__PURE__ */ jsxDEV3("div", {
1180
+ /* @__PURE__ */ jsxDEV4("div", {
930
1181
  className: "space-y-4",
931
1182
  children: [
932
- /* @__PURE__ */ jsxDEV3("div", {
1183
+ /* @__PURE__ */ jsxDEV4("div", {
933
1184
  children: [
934
- /* @__PURE__ */ jsxDEV3("label", {
1185
+ /* @__PURE__ */ jsxDEV4("label", {
935
1186
  htmlFor: "org-name",
936
1187
  className: "font-medium text-sm",
937
1188
  children: "Organization Name"
938
1189
  }, undefined, false, undefined, this),
939
- /* @__PURE__ */ jsxDEV3("input", {
1190
+ /* @__PURE__ */ jsxDEV4("input", {
940
1191
  id: "org-name",
941
1192
  type: "text",
942
1193
  defaultValue: "Demo Organization",
@@ -944,36 +1195,36 @@ function SettingsTab() {
944
1195
  }, undefined, false, undefined, this)
945
1196
  ]
946
1197
  }, undefined, true, undefined, this),
947
- /* @__PURE__ */ jsxDEV3("div", {
1198
+ /* @__PURE__ */ jsxDEV4("div", {
948
1199
  children: [
949
- /* @__PURE__ */ jsxDEV3("label", {
1200
+ /* @__PURE__ */ jsxDEV4("label", {
950
1201
  htmlFor: "timezone",
951
1202
  className: "font-medium text-sm",
952
1203
  children: "Default Timezone"
953
1204
  }, undefined, false, undefined, this),
954
- /* @__PURE__ */ jsxDEV3("select", {
1205
+ /* @__PURE__ */ jsxDEV4("select", {
955
1206
  id: "timezone",
956
1207
  className: "mt-1 block w-full rounded-md border border-input bg-background px-3 py-2",
957
1208
  children: [
958
- /* @__PURE__ */ jsxDEV3("option", {
1209
+ /* @__PURE__ */ jsxDEV4("option", {
959
1210
  children: "UTC"
960
1211
  }, undefined, false, undefined, this),
961
- /* @__PURE__ */ jsxDEV3("option", {
1212
+ /* @__PURE__ */ jsxDEV4("option", {
962
1213
  children: "America/New_York"
963
1214
  }, undefined, false, undefined, this),
964
- /* @__PURE__ */ jsxDEV3("option", {
1215
+ /* @__PURE__ */ jsxDEV4("option", {
965
1216
  children: "Europe/London"
966
1217
  }, undefined, false, undefined, this),
967
- /* @__PURE__ */ jsxDEV3("option", {
1218
+ /* @__PURE__ */ jsxDEV4("option", {
968
1219
  children: "Asia/Tokyo"
969
1220
  }, undefined, false, undefined, this)
970
1221
  ]
971
1222
  }, undefined, true, undefined, this)
972
1223
  ]
973
1224
  }, undefined, true, undefined, this),
974
- /* @__PURE__ */ jsxDEV3("div", {
1225
+ /* @__PURE__ */ jsxDEV4("div", {
975
1226
  className: "pt-2",
976
- children: /* @__PURE__ */ jsxDEV3(Button3, {
1227
+ children: /* @__PURE__ */ jsxDEV4(Button3, {
977
1228
  onPress: () => alert("Settings saved!"),
978
1229
  children: "Save Settings"
979
1230
  }, undefined, false, undefined, this)
@@ -0,0 +1,5 @@
1
+ import type { Project } from '../handlers/saas.handlers';
2
+ export declare function SaasVisualizationOverview({ projects, projectLimit, }: {
3
+ projects: Project[];
4
+ projectLimit: number;
5
+ }): import("react/jsx-runtime").JSX.Element;