@tangle-network/sandbox-ui 0.113.7 → 0.115.0

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 (107) hide show
  1. package/README.md +40 -0
  2. package/dist/WorkflowGraph-B-NsdYz_.js +1961 -0
  3. package/dist/assets.d.ts +214 -206
  4. package/dist/assets.js +1057 -908
  5. package/dist/auth-CWe17Hly.js +37 -0
  6. package/dist/auth.d.ts +2 -30
  7. package/dist/auth.js +2 -15
  8. package/dist/chat-BOvFAe6p.js +903 -0
  9. package/dist/chat.d.ts +2 -230
  10. package/dist/chat.js +2 -34
  11. package/dist/connectors.d.ts +52 -49
  12. package/dist/connectors.js +595 -643
  13. package/dist/dashboard-CZ3VgNPR.js +4969 -0
  14. package/dist/dashboard.d.ts +4 -1297
  15. package/dist/dashboard.js +4 -152
  16. package/dist/editor.d.ts +2 -1
  17. package/dist/editor.js +2 -31
  18. package/dist/files.d.ts +2 -6
  19. package/dist/files.js +2 -33
  20. package/dist/globals.css +75 -3
  21. package/dist/hooks.d.ts +146 -148
  22. package/dist/hooks.js +222 -55
  23. package/dist/index-CKRaj1pM.d.ts +776 -0
  24. package/dist/index-CXX5IpH2.d.ts +2 -0
  25. package/dist/index-CesPlOyx.d.ts +367 -0
  26. package/dist/index-DPePq7c8.d.ts +1340 -0
  27. package/dist/index-DiyLLZuJ.d.ts +230 -0
  28. package/dist/index-DvmZLMT1.d.ts +30 -0
  29. package/dist/index-PRM636Ex.d.ts +86 -0
  30. package/dist/index.d.ts +21 -33
  31. package/dist/index.js +21 -701
  32. package/dist/info-panel-C9cqDzOL.js +594 -0
  33. package/dist/integrations.d.ts +133 -141
  34. package/dist/integrations.js +491 -673
  35. package/dist/markdown.d.ts +2 -1
  36. package/dist/markdown.js +2 -13
  37. package/dist/model-I-NIxeM-.js +1250 -0
  38. package/dist/model-brand-B9A4H9pJ.d.ts +98 -0
  39. package/dist/model-brand-hMyDTUqB.js +624 -0
  40. package/dist/motion-DkyBRJb9.js +37 -0
  41. package/dist/openui.d.ts +2 -1
  42. package/dist/openui.js +2 -7
  43. package/dist/pages.d.ts +307 -300
  44. package/dist/pages.js +4404 -4181
  45. package/dist/primitives-Dh1vG6J3.js +113 -0
  46. package/dist/primitives.d.ts +2 -74
  47. package/dist/primitives.js +2 -204
  48. package/dist/provider-logo-DjqmConF.js +311 -0
  49. package/dist/run.d.ts +2 -1
  50. package/dist/run.js +2 -23
  51. package/dist/sdk-hooks.d.ts +3 -4
  52. package/dist/sdk-hooks.js +3 -31
  53. package/dist/sidecar-DgH_vQ6m.d.ts +9 -0
  54. package/dist/stores.d.ts +14 -15
  55. package/dist/stores.js +13 -81
  56. package/dist/styles.css +75 -3
  57. package/dist/template-card-L-4gmjx2.d.ts +90 -0
  58. package/dist/terminal-CN9ZgHRt.js +197 -0
  59. package/dist/terminal.d.ts +60 -60
  60. package/dist/terminal.js +2 -10
  61. package/dist/tokens.css +51 -0
  62. package/dist/types.d.ts +4 -11
  63. package/dist/types.js +0 -1
  64. package/dist/use-pty-session-C8cE0adT.js +669 -0
  65. package/dist/use-sidecar-auth-CCTJcrq7.d.ts +145 -0
  66. package/dist/use-sidecar-auth-DkdcufOz.js +742 -0
  67. package/dist/utils-DzWbktWG.js +2 -0
  68. package/dist/utils.d.ts +2 -1
  69. package/dist/utils.js +2 -37
  70. package/dist/workbench-ztU44Jt2.js +8455 -0
  71. package/dist/workbench.d.ts +2 -310
  72. package/dist/workbench.js +2 -44
  73. package/dist/workflows.d.ts +341 -339
  74. package/dist/workflows.js +74 -109
  75. package/dist/workspace-B6AtI6ld.js +2510 -0
  76. package/dist/workspace.d.ts +2 -761
  77. package/dist/workspace.js +2 -51
  78. package/package.json +46 -40
  79. package/dist/WorkflowGraph-2QOORYIR.js +0 -1722
  80. package/dist/chunk-2BUPSB7O.js +0 -0
  81. package/dist/chunk-3KBNPQQF.js +0 -2697
  82. package/dist/chunk-3LIXVEEE.js +0 -279
  83. package/dist/chunk-72UF2H5H.js +0 -707
  84. package/dist/chunk-AI25G5MX.js +0 -944
  85. package/dist/chunk-ANSC5AFC.js +0 -314
  86. package/dist/chunk-AZ3AWMTM.js +0 -8
  87. package/dist/chunk-BGVEHENC.js +0 -10
  88. package/dist/chunk-CZ7CSFO4.js +0 -39
  89. package/dist/chunk-DYXXYGS4.js +0 -4700
  90. package/dist/chunk-EI44GEQ5.js +0 -6
  91. package/dist/chunk-IACRDXER.js +0 -219
  92. package/dist/chunk-IOB2PW5Z.js +0 -55
  93. package/dist/chunk-M4K7ZGR2.js +0 -24
  94. package/dist/chunk-MYZAW4RX.js +0 -665
  95. package/dist/chunk-OMUIPJQZ.js +0 -555
  96. package/dist/chunk-RQZRXKMR.js +0 -398
  97. package/dist/chunk-SOKKTB7W.js +0 -230
  98. package/dist/chunk-TADGS4Q7.js +0 -1010
  99. package/dist/chunk-UCQNOUN3.js +0 -7964
  100. package/dist/chunk-ULPLRBMF.js +0 -34
  101. package/dist/chunk-WID73FPH.js +0 -89
  102. package/dist/chunk-X3YXP7FG.js +0 -38
  103. package/dist/logo-DiAjq759.d.ts +0 -15
  104. package/dist/model-brand-BNnaUKKZ.d.ts +0 -99
  105. package/dist/ports-list-CDIvTNnX.d.ts +0 -17
  106. package/dist/sdk-hooks-Djkjq4cp.d.ts +0 -145
  107. package/dist/template-card-Bn-Bw5xC.d.ts +0 -87
@@ -0,0 +1,594 @@
1
+ import { t as cn } from "./utils-DzWbktWG.js";
2
+ import { Badge, Button, Card, CardContent, CardDescription, CardHeader, CardTitle, Progress } from "@tangle-network/ui/primitives";
3
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
4
+ import * as React$1 from "react";
5
+ import { ArrowRight, Check, Zap } from "lucide-react";
6
+ //#region src/dashboard/billing-dashboard.tsx
7
+ const variantColors = { sandbox: {
8
+ accent: "text-[var(--accent-text)]",
9
+ accentBg: "bg-[var(--accent-surface-soft)]",
10
+ border: "border-[var(--border-accent)]",
11
+ progress: "bg-[image:var(--accent-gradient-strong)]"
12
+ } };
13
+ function formatCredits(value) {
14
+ if (value >= 1e6) return `${(value / 1e6).toFixed(1)}M`;
15
+ if (value >= 1e3) return `${(value / 1e3).toFixed(1)}K`;
16
+ return value.toLocaleString();
17
+ }
18
+ function formatDate$1(dateStr) {
19
+ return new Date(dateStr).toLocaleDateString("en-US", {
20
+ month: "long",
21
+ day: "numeric",
22
+ year: "numeric"
23
+ });
24
+ }
25
+ function getStatusBadgeVariant(status) {
26
+ switch (status.toLowerCase()) {
27
+ case "active": return "success";
28
+ case "trialing":
29
+ case "past_due": return "warning";
30
+ case "canceled":
31
+ case "unpaid": return "error";
32
+ default: return "secondary";
33
+ }
34
+ }
35
+ function CreditCardIcon({ className }) {
36
+ return /* @__PURE__ */ jsxs("svg", {
37
+ xmlns: "http://www.w3.org/2000/svg",
38
+ viewBox: "0 0 24 24",
39
+ fill: "none",
40
+ stroke: "currentColor",
41
+ strokeWidth: "2",
42
+ strokeLinecap: "round",
43
+ strokeLinejoin: "round",
44
+ className: cn("h-5 w-5", className),
45
+ children: [
46
+ /* @__PURE__ */ jsx("title", { children: "Credit card icon" }),
47
+ /* @__PURE__ */ jsx("rect", {
48
+ width: "20",
49
+ height: "14",
50
+ x: "2",
51
+ y: "5",
52
+ rx: "2"
53
+ }),
54
+ /* @__PURE__ */ jsx("line", {
55
+ x1: "2",
56
+ x2: "22",
57
+ y1: "10",
58
+ y2: "10"
59
+ })
60
+ ]
61
+ });
62
+ }
63
+ function CoinsIcon({ className }) {
64
+ return /* @__PURE__ */ jsxs("svg", {
65
+ xmlns: "http://www.w3.org/2000/svg",
66
+ viewBox: "0 0 24 24",
67
+ fill: "none",
68
+ stroke: "currentColor",
69
+ strokeWidth: "2",
70
+ strokeLinecap: "round",
71
+ strokeLinejoin: "round",
72
+ className: cn("h-5 w-5", className),
73
+ children: [
74
+ /* @__PURE__ */ jsx("title", { children: "Coins icon" }),
75
+ /* @__PURE__ */ jsx("circle", {
76
+ cx: "8",
77
+ cy: "8",
78
+ r: "6"
79
+ }),
80
+ /* @__PURE__ */ jsx("path", { d: "M18.09 10.37A6 6 0 1 1 10.34 18" }),
81
+ /* @__PURE__ */ jsx("path", { d: "M7 6h1v4" }),
82
+ /* @__PURE__ */ jsx("path", { d: "m16.71 13.88.7.71-2.82 2.82" })
83
+ ]
84
+ });
85
+ }
86
+ function ChartIcon({ className }) {
87
+ return /* @__PURE__ */ jsxs("svg", {
88
+ xmlns: "http://www.w3.org/2000/svg",
89
+ viewBox: "0 0 24 24",
90
+ fill: "none",
91
+ stroke: "currentColor",
92
+ strokeWidth: "2",
93
+ strokeLinecap: "round",
94
+ strokeLinejoin: "round",
95
+ className: cn("h-5 w-5", className),
96
+ children: [
97
+ /* @__PURE__ */ jsx("title", { children: "Chart icon" }),
98
+ /* @__PURE__ */ jsx("path", { d: "M3 3v18h18" }),
99
+ /* @__PURE__ */ jsx("path", { d: "m19 9-5 5-4-4-3 3" })
100
+ ]
101
+ });
102
+ }
103
+ function BillingDashboard({ subscription, balance, usage, onManageSubscription, onAddCredits, variant = "sandbox", className, cardClassName }) {
104
+ const colors = variantColors[variant];
105
+ const totalCredits = balance.available + balance.used;
106
+ const usagePercent = totalCredits > 0 ? balance.used / totalCredits * 100 : 0;
107
+ const sortedModels = Object.entries(usage.byModel).sort(([, a], [, b]) => b - a);
108
+ return /* @__PURE__ */ jsxs("div", {
109
+ className: cn("grid gap-6 lg:grid-cols-3", className),
110
+ children: [
111
+ /* @__PURE__ */ jsxs(Card, {
112
+ variant,
113
+ className: cn("lg:col-span-1", cardClassName),
114
+ children: [/* @__PURE__ */ jsx(CardHeader, { children: /* @__PURE__ */ jsxs("div", {
115
+ className: "flex items-center justify-between",
116
+ children: [/* @__PURE__ */ jsxs(CardTitle, {
117
+ className: "flex items-center gap-2 text-base",
118
+ children: [/* @__PURE__ */ jsx(CreditCardIcon, { className: colors.accent }), "Current Plan"]
119
+ }), subscription && /* @__PURE__ */ jsx(Badge, {
120
+ variant: getStatusBadgeVariant(subscription.status),
121
+ children: subscription.status
122
+ })]
123
+ }) }), /* @__PURE__ */ jsx(CardContent, {
124
+ className: "space-y-4",
125
+ children: subscription ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("p", {
126
+ className: cn("font-bold text-2xl", colors.accent),
127
+ children: subscription.tierName
128
+ }), /* @__PURE__ */ jsxs("p", {
129
+ className: "text-muted-foreground text-sm",
130
+ children: ["Renews ", formatDate$1(subscription.renewsAt)]
131
+ })] }), /* @__PURE__ */ jsx(Button, {
132
+ variant: "outline",
133
+ className: "w-full",
134
+ onClick: onManageSubscription,
135
+ children: "Manage Subscription"
136
+ })] }) : /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("p", {
137
+ className: "font-bold text-2xl text-muted-foreground",
138
+ children: "No Active Plan"
139
+ }), /* @__PURE__ */ jsx("p", {
140
+ className: "text-muted-foreground text-sm",
141
+ children: "Subscribe to get started"
142
+ })] }), /* @__PURE__ */ jsx(Button, {
143
+ variant,
144
+ className: "w-full",
145
+ onClick: onManageSubscription,
146
+ children: "View Plans"
147
+ })] })
148
+ })]
149
+ }),
150
+ /* @__PURE__ */ jsxs(Card, {
151
+ variant,
152
+ className: cn("lg:col-span-1", cardClassName),
153
+ children: [/* @__PURE__ */ jsxs(CardHeader, { children: [/* @__PURE__ */ jsxs(CardTitle, {
154
+ className: "flex items-center gap-2 text-base",
155
+ children: [/* @__PURE__ */ jsx(CoinsIcon, { className: colors.accent }), "Credit Balance"]
156
+ }), /* @__PURE__ */ jsxs(CardDescription, { children: [formatCredits(balance.available), " credits remaining"] })] }), /* @__PURE__ */ jsxs(CardContent, {
157
+ className: "space-y-4",
158
+ children: [/* @__PURE__ */ jsxs("div", {
159
+ className: "space-y-2",
160
+ children: [
161
+ /* @__PURE__ */ jsxs("div", {
162
+ className: "flex items-center justify-between text-sm",
163
+ children: [/* @__PURE__ */ jsx("span", {
164
+ className: "text-muted-foreground",
165
+ children: "Used"
166
+ }), /* @__PURE__ */ jsx("span", {
167
+ className: "font-medium",
168
+ children: formatCredits(balance.used)
169
+ })]
170
+ }),
171
+ /* @__PURE__ */ jsx(Progress, {
172
+ value: usagePercent,
173
+ variant,
174
+ className: "h-3"
175
+ }),
176
+ /* @__PURE__ */ jsxs("div", {
177
+ className: "flex items-center justify-between text-sm",
178
+ children: [/* @__PURE__ */ jsx("span", {
179
+ className: "text-muted-foreground",
180
+ children: "Available"
181
+ }), /* @__PURE__ */ jsx("span", {
182
+ className: cn("font-medium", colors.accent),
183
+ children: formatCredits(balance.available)
184
+ })]
185
+ })
186
+ ]
187
+ }), /* @__PURE__ */ jsx(Button, {
188
+ variant,
189
+ className: "w-full",
190
+ onClick: onAddCredits,
191
+ children: "Add Credits"
192
+ })]
193
+ })]
194
+ }),
195
+ /* @__PURE__ */ jsxs(Card, {
196
+ variant,
197
+ className: cn("lg:col-span-1", cardClassName),
198
+ children: [/* @__PURE__ */ jsxs(CardHeader, { children: [/* @__PURE__ */ jsxs(CardTitle, {
199
+ className: "flex items-center gap-2 text-base",
200
+ children: [/* @__PURE__ */ jsx(ChartIcon, { className: colors.accent }), "Usage Breakdown"]
201
+ }), /* @__PURE__ */ jsx(CardDescription, { children: usage.period })] }), /* @__PURE__ */ jsxs(CardContent, {
202
+ className: "space-y-4",
203
+ children: [/* @__PURE__ */ jsxs("div", {
204
+ className: "flex items-baseline justify-between",
205
+ children: [/* @__PURE__ */ jsx("span", {
206
+ className: "text-muted-foreground text-sm",
207
+ children: "Total Usage"
208
+ }), /* @__PURE__ */ jsx("span", {
209
+ className: cn("font-bold text-2xl", colors.accent),
210
+ children: formatCredits(usage.total)
211
+ })]
212
+ }), /* @__PURE__ */ jsxs("div", {
213
+ className: "space-y-3",
214
+ children: [/* @__PURE__ */ jsx("p", {
215
+ className: "font-medium text-muted-foreground text-xs uppercase tracking-wider",
216
+ children: "By Model"
217
+ }), /* @__PURE__ */ jsxs("div", {
218
+ className: "space-y-2",
219
+ children: [
220
+ sortedModels.slice(0, 5).map(([model, credits]) => {
221
+ const modelPercent = usage.total > 0 ? credits / usage.total * 100 : 0;
222
+ return /* @__PURE__ */ jsxs("div", {
223
+ className: "space-y-1",
224
+ children: [/* @__PURE__ */ jsxs("div", {
225
+ className: "flex items-center justify-between text-sm",
226
+ children: [/* @__PURE__ */ jsx("span", {
227
+ className: "truncate text-muted-foreground",
228
+ children: model
229
+ }), /* @__PURE__ */ jsx("span", {
230
+ className: "ml-2 font-medium",
231
+ children: formatCredits(credits)
232
+ })]
233
+ }), /* @__PURE__ */ jsx("div", {
234
+ className: "h-1.5 w-full overflow-hidden rounded-full bg-muted",
235
+ children: /* @__PURE__ */ jsx("div", {
236
+ className: cn("h-full rounded-full transition-all", variant === "sandbox" && colors.progress),
237
+ style: { width: `${modelPercent}%` }
238
+ })
239
+ })]
240
+ }, model);
241
+ }),
242
+ sortedModels.length > 5 && /* @__PURE__ */ jsxs("p", {
243
+ className: "text-muted-foreground text-xs",
244
+ children: [
245
+ "+",
246
+ sortedModels.length - 5,
247
+ " more models"
248
+ ]
249
+ }),
250
+ sortedModels.length === 0 && /* @__PURE__ */ jsx("p", {
251
+ className: "text-muted-foreground text-sm",
252
+ children: "No usage this period"
253
+ })
254
+ ]
255
+ })]
256
+ })]
257
+ })]
258
+ })
259
+ ]
260
+ });
261
+ }
262
+ //#endregion
263
+ //#region src/dashboard/pricing-page.tsx
264
+ /**
265
+ * Formats an integer cent amount as a human-readable USD price.
266
+ * Whole-dollar amounts omit decimals ($10), fractional amounts show two ($10.99).
267
+ * Returns "$0" for non-finite or negative inputs.
268
+ * @param cents - Amount in whole US cents (e.g. 1099 for $10.99).
269
+ */
270
+ function formatPrice(cents) {
271
+ if (!Number.isFinite(cents) || cents < 0) return "$0";
272
+ return cents % 100 === 0 ? `$${cents / 100}` : `$${(cents / 100).toFixed(2)}`;
273
+ }
274
+ function PricingPage({ tiers, currentTierId, billingPeriod, onBillingPeriodChange, onSelectTier, loading = false, className }) {
275
+ const tiersWithRecommended = tiers.map((tier, i) => ({
276
+ ...tier,
277
+ recommended: tier.recommended ?? (tiers.length === 3 && i === 1)
278
+ }));
279
+ return /* @__PURE__ */ jsxs("div", {
280
+ className: cn("w-full space-y-10", className),
281
+ children: [/* @__PURE__ */ jsx("div", {
282
+ className: "flex justify-center",
283
+ children: /* @__PURE__ */ jsxs("div", {
284
+ className: "inline-flex items-center rounded-full border border-[var(--md3-outline-variant)] bg-surface-container-low p-1",
285
+ children: [/* @__PURE__ */ jsx("button", {
286
+ type: "button",
287
+ onClick: () => onBillingPeriodChange("monthly"),
288
+ className: cn("rounded-full px-5 py-2 text-sm font-medium transition-all", billingPeriod === "monthly" ? "bg-surface-container-high text-foreground shadow-sm" : "text-muted-foreground hover:text-foreground"),
289
+ children: "Monthly"
290
+ }), /* @__PURE__ */ jsxs("button", {
291
+ type: "button",
292
+ onClick: () => onBillingPeriodChange("yearly"),
293
+ className: cn("rounded-full px-5 py-2 text-sm font-medium transition-all", billingPeriod === "yearly" ? "bg-surface-container-high text-foreground shadow-sm" : "text-muted-foreground hover:text-foreground"),
294
+ children: ["Yearly", /* @__PURE__ */ jsx("span", {
295
+ className: "ml-2 rounded-full bg-[var(--surface-success-bg)] px-2 py-0.5 text-[10px] font-bold text-[var(--surface-success-text)]",
296
+ children: "Save 20%"
297
+ })]
298
+ })]
299
+ })
300
+ }), /* @__PURE__ */ jsx("div", {
301
+ className: "grid grid-cols-1 gap-6 lg:grid-cols-3 items-start",
302
+ children: tiersWithRecommended.map((tier) => {
303
+ const isCurrentTier = tier.id === currentTierId;
304
+ const isRecommended = tier.recommended;
305
+ const isFree = tier.monthlyPriceCents === 0;
306
+ const price = billingPeriod === "yearly" && tier.yearlyPriceCents !== void 0 ? tier.yearlyPriceCents : tier.monthlyPriceCents;
307
+ const displayPrice = billingPeriod === "yearly" ? Math.round(price / 12) : price;
308
+ return /* @__PURE__ */ jsxs("div", {
309
+ className: cn("relative flex flex-col rounded-2xl border bg-surface-container transition-all", isRecommended ? "border-primary shadow-[var(--shadow-glow)] scale-[1.02] z-10" : "border-[var(--md3-outline-variant)] hover:border-primary/30"),
310
+ children: [
311
+ isRecommended && /* @__PURE__ */ jsx("div", {
312
+ className: "absolute -top-4 left-1/2 -translate-x-1/2",
313
+ children: /* @__PURE__ */ jsxs("span", {
314
+ className: "inline-flex items-center gap-1.5 rounded-full bg-primary px-4 py-1.5 text-xs font-bold text-primary-foreground shadow-sm",
315
+ children: [/* @__PURE__ */ jsx(Zap, { className: "h-3 w-3" }), "Most Popular"]
316
+ })
317
+ }),
318
+ isCurrentTier && !isRecommended && /* @__PURE__ */ jsx("div", {
319
+ className: "absolute -top-4 left-1/2 -translate-x-1/2",
320
+ children: /* @__PURE__ */ jsx("span", {
321
+ className: "inline-flex items-center rounded-full bg-surface-container-high border border-[var(--md3-outline-variant)] px-4 py-1.5 text-xs font-bold text-foreground",
322
+ children: "Current Plan"
323
+ })
324
+ }),
325
+ /* @__PURE__ */ jsxs("div", {
326
+ className: cn("flex flex-col p-8", isRecommended && "pt-10"),
327
+ children: [
328
+ /* @__PURE__ */ jsxs("div", {
329
+ className: "mb-6",
330
+ children: [/* @__PURE__ */ jsx("h3", {
331
+ className: "text-lg font-bold text-foreground",
332
+ children: tier.name
333
+ }), /* @__PURE__ */ jsx("p", {
334
+ className: "mt-1 text-sm text-muted-foreground",
335
+ children: tier.description
336
+ })]
337
+ }),
338
+ /* @__PURE__ */ jsxs("div", {
339
+ className: "mb-8",
340
+ children: [/* @__PURE__ */ jsxs("div", {
341
+ className: "flex items-baseline gap-1",
342
+ children: [/* @__PURE__ */ jsx("span", {
343
+ className: cn("text-5xl font-extrabold tracking-tight", isRecommended ? "text-primary" : "text-foreground"),
344
+ children: isFree ? "Free" : formatPrice(displayPrice)
345
+ }), !isFree && /* @__PURE__ */ jsx("span", {
346
+ className: "text-muted-foreground text-sm font-medium",
347
+ children: "/mo"
348
+ })]
349
+ }), billingPeriod === "yearly" && tier.yearlyPriceCents !== void 0 && !isFree && /* @__PURE__ */ jsxs("p", {
350
+ className: "mt-1 text-xs text-muted-foreground",
351
+ children: [formatPrice(tier.yearlyPriceCents), " billed annually"]
352
+ })]
353
+ }),
354
+ /* @__PURE__ */ jsx("button", {
355
+ type: "button",
356
+ onClick: () => onSelectTier(tier.id),
357
+ disabled: isCurrentTier || loading,
358
+ className: cn("w-full rounded-xl py-3 text-sm font-bold transition-all active:scale-[0.98] disabled:opacity-50", isRecommended ? "bg-primary text-primary-foreground hover:bg-primary/90 shadow-sm" : isCurrentTier ? "bg-muted text-muted-foreground border border-[var(--md3-outline-variant)] cursor-default" : "bg-surface-container-high text-foreground border border-[var(--md3-outline-variant)] hover:border-primary/50 hover:bg-surface-container-highest"),
359
+ children: isCurrentTier ? "Current Plan" : isFree ? "Get Started" : "Subscribe"
360
+ }),
361
+ /* @__PURE__ */ jsx("div", { className: "my-8 border-t border-[var(--md3-outline-variant)]" }),
362
+ /* @__PURE__ */ jsx("ul", {
363
+ className: "space-y-3.5 flex-1",
364
+ children: tier.features.map((feature) => /* @__PURE__ */ jsxs("li", {
365
+ className: "flex items-start gap-3",
366
+ children: [/* @__PURE__ */ jsx("div", {
367
+ className: cn("mt-0.5 flex h-5 w-5 shrink-0 items-center justify-center rounded-full", isRecommended ? "bg-primary/10 text-primary" : "bg-surface-container-high text-muted-foreground"),
368
+ children: /* @__PURE__ */ jsx(Check, { className: "h-3 w-3" })
369
+ }), /* @__PURE__ */ jsx("span", {
370
+ className: "text-sm text-foreground/80",
371
+ children: feature
372
+ })]
373
+ }, feature))
374
+ })
375
+ ]
376
+ })
377
+ ]
378
+ }, tier.id);
379
+ })
380
+ })]
381
+ });
382
+ }
383
+ //#endregion
384
+ //#region src/dashboard/usage-chart.tsx
385
+ const colors = {
386
+ bar: "bg-[image:var(--accent-gradient-strong)]",
387
+ barHover: "hover:brightness-110",
388
+ text: "text-[var(--accent-text)]"
389
+ };
390
+ function formatDate(dateStr) {
391
+ return new Date(dateStr).toLocaleDateString("en-US", {
392
+ month: "short",
393
+ day: "numeric"
394
+ });
395
+ }
396
+ function formatValue(value) {
397
+ if (value >= 1e6) return `${(value / 1e6).toFixed(1)}M`;
398
+ if (value >= 1e3) return `${(value / 1e3).toFixed(1)}K`;
399
+ return value.toLocaleString();
400
+ }
401
+ function UsageChart({ data, title, unit, className }) {
402
+ const maxValue = Math.max(...data.map((d) => d.value), 1);
403
+ const total = data.reduce((sum, d) => sum + d.value, 0);
404
+ const [hoveredIndex, setHoveredIndex] = React$1.useState(null);
405
+ const isEmpty = data.length === 0 || total === 0;
406
+ return /* @__PURE__ */ jsxs(Card, {
407
+ className,
408
+ children: [/* @__PURE__ */ jsxs(CardHeader, {
409
+ className: "flex flex-row items-center justify-between gap-3 pb-2",
410
+ children: [/* @__PURE__ */ jsx(CardTitle, {
411
+ className: "min-w-0 truncate font-medium text-base",
412
+ children: title
413
+ }), /* @__PURE__ */ jsxs("div", {
414
+ className: "shrink-0 whitespace-nowrap text-right",
415
+ children: [/* @__PURE__ */ jsx("span", {
416
+ className: cn("font-bold text-2xl", colors.text),
417
+ children: formatValue(total)
418
+ }), /* @__PURE__ */ jsx("span", {
419
+ className: "ml-1 text-muted-foreground text-sm",
420
+ children: unit
421
+ })]
422
+ })]
423
+ }), /* @__PURE__ */ jsx(CardContent, { children: isEmpty ? /* @__PURE__ */ jsxs("div", {
424
+ className: "flex h-48 flex-col items-center justify-center gap-1 text-center",
425
+ children: [/* @__PURE__ */ jsxs("p", {
426
+ className: "font-medium text-sm",
427
+ children: [
428
+ "No ",
429
+ unit,
430
+ " recorded yet"
431
+ ]
432
+ }), /* @__PURE__ */ jsx("p", {
433
+ className: "text-muted-foreground text-xs",
434
+ children: "Usage appears here once activity begins."
435
+ })]
436
+ }) : /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs("div", {
437
+ className: "relative",
438
+ children: [
439
+ /* @__PURE__ */ jsxs("div", {
440
+ className: "absolute top-0 left-0 flex h-48 flex-col justify-between text-muted-foreground text-xs",
441
+ children: [
442
+ /* @__PURE__ */ jsx("span", { children: formatValue(maxValue) }),
443
+ /* @__PURE__ */ jsx("span", { children: formatValue(Math.round(maxValue / 2)) }),
444
+ /* @__PURE__ */ jsx("span", { children: "0" })
445
+ ]
446
+ }),
447
+ /* @__PURE__ */ jsx("div", {
448
+ className: "ml-10 flex h-48 items-end gap-1",
449
+ children: data.map((point, index) => {
450
+ const heightPercent = point.value / maxValue * 100;
451
+ const isHovered = hoveredIndex === index;
452
+ return /* @__PURE__ */ jsxs("div", {
453
+ className: "group relative flex flex-1 flex-col items-center",
454
+ onMouseEnter: () => setHoveredIndex(index),
455
+ onMouseLeave: () => setHoveredIndex(null),
456
+ children: [isHovered && /* @__PURE__ */ jsxs("div", {
457
+ className: "absolute -top-12 z-10 rounded-lg border border-[var(--md3-outline-variant)] bg-surface-container-highest px-3 py-1.5 text-sm shadow-[0_8px_30px_rgba(0,0,0,0.45)] ring-1 ring-[#ffffff14]",
458
+ children: [/* @__PURE__ */ jsxs("p", {
459
+ className: "font-medium",
460
+ children: [
461
+ formatValue(point.value),
462
+ " ",
463
+ unit
464
+ ]
465
+ }), /* @__PURE__ */ jsx("p", {
466
+ className: "text-muted-foreground text-xs",
467
+ children: formatDate(point.date)
468
+ })]
469
+ }), /* @__PURE__ */ jsx("div", {
470
+ className: cn("min-h-[2px] w-full rounded-t-sm transition-all duration-200", colors.bar, colors.barHover, isHovered && "opacity-80"),
471
+ style: { height: `${Math.max(heightPercent, 1)}%` }
472
+ })]
473
+ }, point.date);
474
+ })
475
+ }),
476
+ /* @__PURE__ */ jsx("div", {
477
+ className: "mt-2 ml-10 flex gap-1",
478
+ children: data.map((point, index) => /* @__PURE__ */ jsx("div", {
479
+ className: cn("flex-1 truncate text-center text-muted-foreground text-xs", hoveredIndex === index && colors.text),
480
+ children: data.length <= 7 || index % Math.ceil(data.length / 7) === 0 ? formatDate(point.date) : ""
481
+ }, point.date))
482
+ })
483
+ ]
484
+ }), /* @__PURE__ */ jsxs("div", {
485
+ className: "mt-4 grid grid-cols-3 gap-4 border-[var(--md3-outline-variant)] border-t pt-4",
486
+ children: [
487
+ /* @__PURE__ */ jsxs("div", {
488
+ className: "text-center",
489
+ children: [/* @__PURE__ */ jsx("p", {
490
+ className: "text-muted-foreground text-xs",
491
+ children: "Average"
492
+ }), /* @__PURE__ */ jsxs("p", {
493
+ className: "font-medium",
494
+ children: [
495
+ formatValue(Math.round(total / data.length)),
496
+ " ",
497
+ unit
498
+ ]
499
+ })]
500
+ }),
501
+ /* @__PURE__ */ jsxs("div", {
502
+ className: "text-center",
503
+ children: [/* @__PURE__ */ jsx("p", {
504
+ className: "text-muted-foreground text-xs",
505
+ children: "Peak"
506
+ }), /* @__PURE__ */ jsxs("p", {
507
+ className: "font-medium",
508
+ children: [
509
+ formatValue(maxValue),
510
+ " ",
511
+ unit
512
+ ]
513
+ })]
514
+ }),
515
+ /* @__PURE__ */ jsxs("div", {
516
+ className: "text-center",
517
+ children: [/* @__PURE__ */ jsx("p", {
518
+ className: "text-muted-foreground text-xs",
519
+ children: "Total"
520
+ }), /* @__PURE__ */ jsxs("p", {
521
+ className: cn("font-medium", colors.text),
522
+ children: [
523
+ formatValue(total),
524
+ " ",
525
+ unit
526
+ ]
527
+ })]
528
+ })
529
+ ]
530
+ })] }) })]
531
+ });
532
+ }
533
+ //#endregion
534
+ //#region src/dashboard/template-card.tsx
535
+ function TemplateCard({ template, onUseTemplate, className }) {
536
+ return /* @__PURE__ */ jsxs("div", {
537
+ className: cn("group relative flex flex-col justify-between rounded-xl border border-[var(--md3-outline-variant)] bg-surface-container p-6 transition-colors hover:border-[var(--border-accent)]", className),
538
+ children: [/* @__PURE__ */ jsxs("div", { children: [
539
+ /* @__PURE__ */ jsx("div", {
540
+ className: "mb-4 flex h-12 w-12 items-center justify-center rounded-xl bg-surface-container-high border border-[var(--md3-outline-variant)]",
541
+ children: template.icon ?? /* @__PURE__ */ jsx("span", {
542
+ className: "text-lg font-bold text-primary",
543
+ children: template.name.charAt(0).toUpperCase()
544
+ })
545
+ }),
546
+ /* @__PURE__ */ jsx("h3", {
547
+ className: "mb-1 text-base font-bold text-foreground",
548
+ children: template.name
549
+ }),
550
+ /* @__PURE__ */ jsx("p", {
551
+ className: "text-sm text-muted-foreground leading-relaxed line-clamp-2",
552
+ children: template.description
553
+ }),
554
+ template.tags && template.tags.length > 0 && /* @__PURE__ */ jsx("div", {
555
+ className: "mt-3 flex flex-wrap gap-1.5",
556
+ children: template.tags.map((tag, i) => /* @__PURE__ */ jsx("span", {
557
+ className: "rounded-full bg-surface-container-high px-2 py-0.5 text-[10px] font-medium text-muted-foreground",
558
+ children: tag
559
+ }, `${tag}-${i}`))
560
+ })
561
+ ] }), /* @__PURE__ */ jsxs("button", {
562
+ type: "button",
563
+ onClick: () => onUseTemplate(template.id),
564
+ className: "mt-5 inline-flex w-full items-center justify-center gap-2 rounded-xl bg-primary/10 border border-primary/20 px-4 py-2.5 text-sm font-bold text-primary transition-colors hover:bg-primary hover:text-primary-foreground active:scale-[0.98]",
565
+ children: ["Use Template", /* @__PURE__ */ jsx(ArrowRight, { className: "h-4 w-4 transition-transform group-hover:translate-x-0.5" })]
566
+ })]
567
+ });
568
+ }
569
+ //#endregion
570
+ //#region src/dashboard/info-panel.tsx
571
+ function InfoPanel({ label, title, description, className }) {
572
+ return /* @__PURE__ */ jsxs("div", {
573
+ className: cn("rounded-lg bg-[var(--brand-strong)] p-5 text-[var(--brand-strong-text)] relative overflow-hidden", className),
574
+ children: [/* @__PURE__ */ jsxs("div", {
575
+ className: "relative z-10",
576
+ children: [
577
+ /* @__PURE__ */ jsx("p", {
578
+ className: "text-[10px] font-bold uppercase tracking-widest text-[var(--brand-strong-text-dim)]",
579
+ children: label
580
+ }),
581
+ /* @__PURE__ */ jsx("h3", {
582
+ className: "mt-1 text-lg font-bold",
583
+ children: title
584
+ }),
585
+ /* @__PURE__ */ jsx("p", {
586
+ className: "mt-1 text-sm text-[var(--brand-strong-text-muted)]",
587
+ children: description
588
+ })
589
+ ]
590
+ }), /* @__PURE__ */ jsx("div", { className: "absolute right-0 top-0 h-full w-1/3 bg-white/5 -skew-x-12 translate-x-12 pointer-events-none" })]
591
+ });
592
+ }
593
+ //#endregion
594
+ export { formatPrice as a, PricingPage as i, TemplateCard as n, BillingDashboard as o, UsageChart as r, InfoPanel as t };