@tangle-network/sandbox-ui 0.14.0 → 0.15.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.
- package/dist/auth.d.ts +1 -74
- package/dist/auth.js +1 -4
- package/dist/chat.d.ts +1 -136
- package/dist/chat.js +2 -15
- package/dist/chunk-2BUPSB7O.js +0 -0
- package/dist/chunk-3J6FG3FJ.js +18 -0
- package/dist/chunk-76IQLPW2.js +206 -0
- package/dist/chunk-7ZA5SEK3.js +239 -0
- package/dist/chunk-AZ3AWMTM.js +8 -0
- package/dist/chunk-CMY7W45U.js +380 -0
- package/dist/chunk-EI44GEQ5.js +6 -0
- package/dist/chunk-ENMWGVDL.js +858 -0
- package/dist/{chunk-5OQ27N57.js → chunk-GPT7VKK6.js} +34 -38
- package/dist/chunk-HLZTKSGT.js +2652 -0
- package/dist/chunk-JBGKGLD7.js +16 -0
- package/dist/chunk-NJNME4J4.js +14 -0
- package/dist/chunk-QPAJR74X.js +20 -0
- package/dist/chunk-TK46XFLM.js +28 -0
- package/dist/chunk-WID73FPH.js +89 -0
- package/dist/chunk-YVXK4XRO.js +30 -0
- package/dist/dashboard.d.ts +450 -4
- package/dist/dashboard.js +20 -891
- package/dist/editor.d.ts +1 -120
- package/dist/editor.js +1 -5
- package/dist/files.d.ts +1 -129
- package/dist/files.js +2 -7
- package/dist/globals.css +2 -1265
- package/dist/hooks.d.ts +114 -11
- package/dist/hooks.js +17 -88
- package/dist/index.d.ts +24 -99
- package/dist/index.js +251 -256
- package/dist/markdown.d.ts +1 -29
- package/dist/markdown.js +2 -2
- package/dist/openui.d.ts +8 -115
- package/dist/openui.js +1 -6
- package/dist/pages.d.ts +13 -12
- package/dist/pages.js +91 -115
- package/dist/primitives.d.ts +14 -49
- package/dist/primitives.js +69 -77
- package/dist/run.d.ts +1 -14
- package/dist/run.js +2 -22
- package/dist/sdk-hooks.d.ts +3 -283
- package/dist/sdk-hooks.js +10 -14
- package/dist/stores.d.ts +2 -14
- package/dist/stores.js +11 -39
- package/dist/styles.css +2 -1265
- package/dist/template-card-DStb8boW.d.ts +183 -0
- package/dist/types.d.ts +11 -8
- package/dist/types.js +1 -0
- package/dist/utils.d.ts +1 -44
- package/dist/utils.js +6 -12
- package/dist/workspace.d.ts +5 -10
- package/dist/workspace.js +3 -19
- package/package.json +19 -54
- package/dist/active-sessions-store-CeOmXgv5.d.ts +0 -85
- package/dist/artifact-pane-Bh45Ssco.d.ts +0 -24
- package/dist/branding-DCi5VEik.d.ts +0 -13
- package/dist/button-CMQuQEW_.d.ts +0 -17
- package/dist/chat-container-f4yEs6KN.d.ts +0 -106
- package/dist/chunk-34A66VBG.js +0 -214
- package/dist/chunk-34I7UFSX.js +0 -92
- package/dist/chunk-36QY2W5G.js +0 -802
- package/dist/chunk-4CLN43XT.js +0 -45
- package/dist/chunk-54SQQMMM.js +0 -156
- package/dist/chunk-66EZOYZR.js +0 -102
- package/dist/chunk-BX6AQMUS.js +0 -183
- package/dist/chunk-DI3NZ5ZX.js +0 -192
- package/dist/chunk-DPGIXDAI.js +0 -220
- package/dist/chunk-DXMIEK4K.js +0 -1426
- package/dist/chunk-GSZA3TSY.js +0 -79
- package/dist/chunk-HB5Y37YU.js +0 -54
- package/dist/chunk-LQNEZDRM.js +0 -109
- package/dist/chunk-MA7YKRUP.js +0 -131
- package/dist/chunk-MKTSMWVD.js +0 -109
- package/dist/chunk-MQXABZTB.js +0 -1348
- package/dist/chunk-MT5FJ3ZT.js +0 -186
- package/dist/chunk-NKUPJC34.js +0 -2070
- package/dist/chunk-OEX7NZE3.js +0 -321
- package/dist/chunk-OKLQVY3Y.js +0 -139
- package/dist/chunk-Q56BYXQF.js +0 -61
- package/dist/chunk-QD4QE5P5.js +0 -40
- package/dist/chunk-QDH5GEGY.js +0 -630
- package/dist/chunk-QID2OOMG.js +0 -133
- package/dist/chunk-QMU2PWOU.js +0 -493
- package/dist/chunk-RQHJBTEU.js +0 -10
- package/dist/chunk-T7HMZEVO.js +0 -216
- package/dist/chunk-U6QTHMY6.js +0 -1290
- package/dist/chunk-US6JKJKH.js +0 -124
- package/dist/chunk-VX3XOUEB.js +0 -63
- package/dist/chunk-XLG757B6.js +0 -933
- package/dist/chunk-ZMNSRDMH.js +0 -127
- package/dist/chunk-ZNCEM5CD.js +0 -316
- package/dist/document-editor-pane-A70-EhdQ.d.ts +0 -124
- package/dist/document-editor-pane-TLPVRBBU.js +0 -11
- package/dist/expanded-tool-detail-Dh99mcbY.d.ts +0 -63
- package/dist/file-tabs-BLfxfmAH.d.ts +0 -51
- package/dist/parts-CyGkM6Fp.d.ts +0 -50
- package/dist/run-CtFZ6s-D.d.ts +0 -41
- package/dist/sidebar-drop-zone-tDBsuOH5.d.ts +0 -301
- package/dist/sidecar-CFU2W9j1.d.ts +0 -8
- package/dist/template-card-BAtvcAkU.d.ts +0 -18
- package/dist/tool-call-feed-Bs3MyQMT.d.ts +0 -68
- package/dist/tool-display-Ct9nFAzJ.d.ts +0 -32
- package/dist/usage-chart-CPTcNlGs.d.ts +0 -73
- package/dist/use-sandbox-metrics-DWc0k9Xm.d.ts +0 -153
- package/dist/variant-list-BrHYcBCk.d.ts +0 -540
package/dist/chunk-QID2OOMG.js
DELETED
|
@@ -1,133 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
ToolCallGroup,
|
|
3
|
-
ToolCallStep
|
|
4
|
-
} from "./chunk-MT5FJ3ZT.js";
|
|
5
|
-
import {
|
|
6
|
-
Markdown
|
|
7
|
-
} from "./chunk-T7HMZEVO.js";
|
|
8
|
-
import {
|
|
9
|
-
cn
|
|
10
|
-
} from "./chunk-RQHJBTEU.js";
|
|
11
|
-
|
|
12
|
-
// src/run/tool-call-feed.tsx
|
|
13
|
-
import { jsx } from "react/jsx-runtime";
|
|
14
|
-
function ToolCallFeed({ segments, className }) {
|
|
15
|
-
if (segments.length === 0) return null;
|
|
16
|
-
return /* @__PURE__ */ jsx("div", { className: cn("space-y-1", className), children: segments.map((segment, i) => {
|
|
17
|
-
if (segment.kind === "text") {
|
|
18
|
-
return segment.content.trim() ? /* @__PURE__ */ jsx(Markdown, { children: segment.content }, i) : null;
|
|
19
|
-
}
|
|
20
|
-
if (segment.kind === "tool_call") {
|
|
21
|
-
return /* @__PURE__ */ jsx(
|
|
22
|
-
ToolCallStep,
|
|
23
|
-
{
|
|
24
|
-
type: segment.call.type,
|
|
25
|
-
label: segment.call.label,
|
|
26
|
-
status: segment.call.status,
|
|
27
|
-
detail: segment.call.detail,
|
|
28
|
-
output: segment.call.output,
|
|
29
|
-
duration: segment.call.duration
|
|
30
|
-
},
|
|
31
|
-
segment.call.id || i
|
|
32
|
-
);
|
|
33
|
-
}
|
|
34
|
-
if (segment.kind === "tool_group") {
|
|
35
|
-
return /* @__PURE__ */ jsx(ToolCallGroup, { title: segment.title, children: segment.calls.map((call) => /* @__PURE__ */ jsx(
|
|
36
|
-
ToolCallStep,
|
|
37
|
-
{
|
|
38
|
-
type: call.type,
|
|
39
|
-
label: call.label,
|
|
40
|
-
status: call.status,
|
|
41
|
-
detail: call.detail,
|
|
42
|
-
output: call.output,
|
|
43
|
-
duration: call.duration
|
|
44
|
-
},
|
|
45
|
-
call.id
|
|
46
|
-
)) }, i);
|
|
47
|
-
}
|
|
48
|
-
return null;
|
|
49
|
-
}) });
|
|
50
|
-
}
|
|
51
|
-
function parseToolEvent(event) {
|
|
52
|
-
const { type, data } = event;
|
|
53
|
-
if (type === "tool.invocation" || type === "tool_use") {
|
|
54
|
-
const toolName = data.name || data.tool || "unknown";
|
|
55
|
-
const input = data.input;
|
|
56
|
-
return {
|
|
57
|
-
id: data.id || data.toolUseId || createId(),
|
|
58
|
-
type: mapToolName(toolName),
|
|
59
|
-
label: formatToolLabel(toolName, input),
|
|
60
|
-
status: "running",
|
|
61
|
-
detail: input ? formatToolInput(toolName, input) : void 0
|
|
62
|
-
};
|
|
63
|
-
}
|
|
64
|
-
if (type === "tool.result" || type === "tool_result") {
|
|
65
|
-
return {
|
|
66
|
-
id: data.id || data.toolUseId || "",
|
|
67
|
-
type: mapToolName(data.name || data.tool || "unknown"),
|
|
68
|
-
label: formatToolLabel(data.name || data.tool || "unknown"),
|
|
69
|
-
status: data.error ? "error" : "success",
|
|
70
|
-
output: truncate(data.output || data.result || "", 500),
|
|
71
|
-
duration: data.duration
|
|
72
|
-
};
|
|
73
|
-
}
|
|
74
|
-
return null;
|
|
75
|
-
}
|
|
76
|
-
function createId() {
|
|
77
|
-
if (typeof globalThis.crypto !== "undefined" && typeof globalThis.crypto.randomUUID === "function") {
|
|
78
|
-
try {
|
|
79
|
-
return globalThis.crypto.randomUUID();
|
|
80
|
-
} catch {
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
return `tool_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 10)}`;
|
|
84
|
-
}
|
|
85
|
-
function mapToolName(name) {
|
|
86
|
-
const lower = name.toLowerCase();
|
|
87
|
-
if (lower.includes("bash") || lower.includes("terminal") || lower.includes("exec")) return "bash";
|
|
88
|
-
if (lower.includes("read") || lower.includes("cat")) return "read";
|
|
89
|
-
if (lower.includes("write") || lower.includes("create")) return "write";
|
|
90
|
-
if (lower.includes("edit") || lower.includes("replace")) return "edit";
|
|
91
|
-
if (lower.includes("glob") || lower.includes("find")) return "glob";
|
|
92
|
-
if (lower.includes("grep") || lower.includes("search")) return "grep";
|
|
93
|
-
if (lower.includes("list") || lower.includes("ls")) return "list";
|
|
94
|
-
if (lower.includes("inspect")) return "inspect";
|
|
95
|
-
if (lower.includes("audit")) return "audit";
|
|
96
|
-
return "unknown";
|
|
97
|
-
}
|
|
98
|
-
function formatToolLabel(toolName, input) {
|
|
99
|
-
const lower = toolName.toLowerCase();
|
|
100
|
-
if (lower.includes("bash") && input?.command) {
|
|
101
|
-
const cmd = String(input.command);
|
|
102
|
-
return cmd.length > 80 ? `${cmd.slice(0, 77)}...` : cmd;
|
|
103
|
-
}
|
|
104
|
-
if ((lower.includes("read") || lower.includes("cat")) && input?.path) {
|
|
105
|
-
return `Read ${input.path}`;
|
|
106
|
-
}
|
|
107
|
-
if (lower.includes("write") && input?.path) {
|
|
108
|
-
return `Write ${input.path}`;
|
|
109
|
-
}
|
|
110
|
-
if (lower.includes("edit") && input?.path) {
|
|
111
|
-
return `Edit ${input.path}`;
|
|
112
|
-
}
|
|
113
|
-
if (lower.includes("glob") && input?.pattern) {
|
|
114
|
-
return `Find ${input.pattern}`;
|
|
115
|
-
}
|
|
116
|
-
if (lower.includes("grep") && input?.pattern) {
|
|
117
|
-
return `Search for ${input.pattern}`;
|
|
118
|
-
}
|
|
119
|
-
return toolName;
|
|
120
|
-
}
|
|
121
|
-
function formatToolInput(toolName, input) {
|
|
122
|
-
if (input.command) return String(input.command);
|
|
123
|
-
if (input.path) return String(input.path);
|
|
124
|
-
return JSON.stringify(input, null, 2).slice(0, 300);
|
|
125
|
-
}
|
|
126
|
-
function truncate(text, max) {
|
|
127
|
-
return text.length > max ? text.slice(0, max - 3) + "..." : text;
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
export {
|
|
131
|
-
ToolCallFeed,
|
|
132
|
-
parseToolEvent
|
|
133
|
-
};
|
package/dist/chunk-QMU2PWOU.js
DELETED
|
@@ -1,493 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
Progress
|
|
3
|
-
} from "./chunk-66EZOYZR.js";
|
|
4
|
-
import {
|
|
5
|
-
Badge,
|
|
6
|
-
Card,
|
|
7
|
-
CardContent,
|
|
8
|
-
CardDescription,
|
|
9
|
-
CardHeader,
|
|
10
|
-
CardTitle
|
|
11
|
-
} from "./chunk-ZMNSRDMH.js";
|
|
12
|
-
import {
|
|
13
|
-
Button
|
|
14
|
-
} from "./chunk-MKTSMWVD.js";
|
|
15
|
-
import {
|
|
16
|
-
cn
|
|
17
|
-
} from "./chunk-RQHJBTEU.js";
|
|
18
|
-
|
|
19
|
-
// src/dashboard/billing-dashboard.tsx
|
|
20
|
-
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
21
|
-
var variantColors = {
|
|
22
|
-
sandbox: {
|
|
23
|
-
accent: "text-[var(--accent-text)]",
|
|
24
|
-
accentBg: "bg-[var(--accent-surface-soft)]",
|
|
25
|
-
border: "border-[var(--border-accent)]",
|
|
26
|
-
progress: "bg-[image:var(--accent-gradient-strong)]"
|
|
27
|
-
}
|
|
28
|
-
};
|
|
29
|
-
function formatCredits(value) {
|
|
30
|
-
if (value >= 1e6) {
|
|
31
|
-
return `${(value / 1e6).toFixed(1)}M`;
|
|
32
|
-
}
|
|
33
|
-
if (value >= 1e3) {
|
|
34
|
-
return `${(value / 1e3).toFixed(1)}K`;
|
|
35
|
-
}
|
|
36
|
-
return value.toLocaleString();
|
|
37
|
-
}
|
|
38
|
-
function formatDate(dateStr) {
|
|
39
|
-
const date = new Date(dateStr);
|
|
40
|
-
return date.toLocaleDateString("en-US", {
|
|
41
|
-
month: "long",
|
|
42
|
-
day: "numeric",
|
|
43
|
-
year: "numeric"
|
|
44
|
-
});
|
|
45
|
-
}
|
|
46
|
-
function getStatusBadgeVariant(status) {
|
|
47
|
-
switch (status.toLowerCase()) {
|
|
48
|
-
case "active":
|
|
49
|
-
return "success";
|
|
50
|
-
case "trialing":
|
|
51
|
-
case "past_due":
|
|
52
|
-
return "warning";
|
|
53
|
-
case "canceled":
|
|
54
|
-
case "unpaid":
|
|
55
|
-
return "error";
|
|
56
|
-
default:
|
|
57
|
-
return "secondary";
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
function CreditCardIcon({ className }) {
|
|
61
|
-
return /* @__PURE__ */ jsxs(
|
|
62
|
-
"svg",
|
|
63
|
-
{
|
|
64
|
-
xmlns: "http://www.w3.org/2000/svg",
|
|
65
|
-
viewBox: "0 0 24 24",
|
|
66
|
-
fill: "none",
|
|
67
|
-
stroke: "currentColor",
|
|
68
|
-
strokeWidth: "2",
|
|
69
|
-
strokeLinecap: "round",
|
|
70
|
-
strokeLinejoin: "round",
|
|
71
|
-
className: cn("h-5 w-5", className),
|
|
72
|
-
children: [
|
|
73
|
-
/* @__PURE__ */ jsx("title", { children: "Credit card icon" }),
|
|
74
|
-
/* @__PURE__ */ jsx("rect", { width: "20", height: "14", x: "2", y: "5", rx: "2" }),
|
|
75
|
-
/* @__PURE__ */ jsx("line", { x1: "2", x2: "22", y1: "10", y2: "10" })
|
|
76
|
-
]
|
|
77
|
-
}
|
|
78
|
-
);
|
|
79
|
-
}
|
|
80
|
-
function CoinsIcon({ className }) {
|
|
81
|
-
return /* @__PURE__ */ jsxs(
|
|
82
|
-
"svg",
|
|
83
|
-
{
|
|
84
|
-
xmlns: "http://www.w3.org/2000/svg",
|
|
85
|
-
viewBox: "0 0 24 24",
|
|
86
|
-
fill: "none",
|
|
87
|
-
stroke: "currentColor",
|
|
88
|
-
strokeWidth: "2",
|
|
89
|
-
strokeLinecap: "round",
|
|
90
|
-
strokeLinejoin: "round",
|
|
91
|
-
className: cn("h-5 w-5", className),
|
|
92
|
-
children: [
|
|
93
|
-
/* @__PURE__ */ jsx("title", { children: "Coins icon" }),
|
|
94
|
-
/* @__PURE__ */ jsx("circle", { cx: "8", cy: "8", r: "6" }),
|
|
95
|
-
/* @__PURE__ */ jsx("path", { d: "M18.09 10.37A6 6 0 1 1 10.34 18" }),
|
|
96
|
-
/* @__PURE__ */ jsx("path", { d: "M7 6h1v4" }),
|
|
97
|
-
/* @__PURE__ */ jsx("path", { d: "m16.71 13.88.7.71-2.82 2.82" })
|
|
98
|
-
]
|
|
99
|
-
}
|
|
100
|
-
);
|
|
101
|
-
}
|
|
102
|
-
function ChartIcon({ className }) {
|
|
103
|
-
return /* @__PURE__ */ jsxs(
|
|
104
|
-
"svg",
|
|
105
|
-
{
|
|
106
|
-
xmlns: "http://www.w3.org/2000/svg",
|
|
107
|
-
viewBox: "0 0 24 24",
|
|
108
|
-
fill: "none",
|
|
109
|
-
stroke: "currentColor",
|
|
110
|
-
strokeWidth: "2",
|
|
111
|
-
strokeLinecap: "round",
|
|
112
|
-
strokeLinejoin: "round",
|
|
113
|
-
className: cn("h-5 w-5", className),
|
|
114
|
-
children: [
|
|
115
|
-
/* @__PURE__ */ jsx("title", { children: "Chart icon" }),
|
|
116
|
-
/* @__PURE__ */ jsx("path", { d: "M3 3v18h18" }),
|
|
117
|
-
/* @__PURE__ */ jsx("path", { d: "m19 9-5 5-4-4-3 3" })
|
|
118
|
-
]
|
|
119
|
-
}
|
|
120
|
-
);
|
|
121
|
-
}
|
|
122
|
-
function BillingDashboard({
|
|
123
|
-
subscription,
|
|
124
|
-
balance,
|
|
125
|
-
usage,
|
|
126
|
-
onManageSubscription,
|
|
127
|
-
onAddCredits,
|
|
128
|
-
variant = "sandbox",
|
|
129
|
-
className,
|
|
130
|
-
cardClassName
|
|
131
|
-
}) {
|
|
132
|
-
const colors2 = variantColors[variant];
|
|
133
|
-
const totalCredits = balance.available + balance.used;
|
|
134
|
-
const usagePercent = totalCredits > 0 ? balance.used / totalCredits * 100 : 0;
|
|
135
|
-
const sortedModels = Object.entries(usage.byModel).sort(
|
|
136
|
-
([, a], [, b]) => b - a
|
|
137
|
-
);
|
|
138
|
-
return /* @__PURE__ */ jsxs("div", { className: cn("grid gap-6 lg:grid-cols-3", className), children: [
|
|
139
|
-
/* @__PURE__ */ jsxs(Card, { variant, className: cn("lg:col-span-1", cardClassName), children: [
|
|
140
|
-
/* @__PURE__ */ jsx(CardHeader, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
|
|
141
|
-
/* @__PURE__ */ jsxs(CardTitle, { className: "flex items-center gap-2 text-base", children: [
|
|
142
|
-
/* @__PURE__ */ jsx(CreditCardIcon, { className: colors2.accent }),
|
|
143
|
-
"Current Plan"
|
|
144
|
-
] }),
|
|
145
|
-
subscription && /* @__PURE__ */ jsx(Badge, { variant: getStatusBadgeVariant(subscription.status), children: subscription.status })
|
|
146
|
-
] }) }),
|
|
147
|
-
/* @__PURE__ */ jsx(CardContent, { className: "space-y-4", children: subscription ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
148
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
149
|
-
/* @__PURE__ */ jsx("p", { className: cn("font-bold text-2xl", colors2.accent), children: subscription.tierName }),
|
|
150
|
-
/* @__PURE__ */ jsxs("p", { className: "text-muted-foreground text-sm", children: [
|
|
151
|
-
"Renews ",
|
|
152
|
-
formatDate(subscription.renewsAt)
|
|
153
|
-
] })
|
|
154
|
-
] }),
|
|
155
|
-
/* @__PURE__ */ jsx(
|
|
156
|
-
Button,
|
|
157
|
-
{
|
|
158
|
-
variant: "outline",
|
|
159
|
-
className: "w-full",
|
|
160
|
-
onClick: onManageSubscription,
|
|
161
|
-
children: "Manage Subscription"
|
|
162
|
-
}
|
|
163
|
-
)
|
|
164
|
-
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
165
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
166
|
-
/* @__PURE__ */ jsx("p", { className: "font-bold text-2xl text-muted-foreground", children: "No Active Plan" }),
|
|
167
|
-
/* @__PURE__ */ jsx("p", { className: "text-muted-foreground text-sm", children: "Subscribe to get started" })
|
|
168
|
-
] }),
|
|
169
|
-
/* @__PURE__ */ jsx(
|
|
170
|
-
Button,
|
|
171
|
-
{
|
|
172
|
-
variant,
|
|
173
|
-
className: "w-full",
|
|
174
|
-
onClick: onManageSubscription,
|
|
175
|
-
children: "View Plans"
|
|
176
|
-
}
|
|
177
|
-
)
|
|
178
|
-
] }) })
|
|
179
|
-
] }),
|
|
180
|
-
/* @__PURE__ */ jsxs(Card, { variant, className: cn("lg:col-span-1", cardClassName), children: [
|
|
181
|
-
/* @__PURE__ */ jsxs(CardHeader, { children: [
|
|
182
|
-
/* @__PURE__ */ jsxs(CardTitle, { className: "flex items-center gap-2 text-base", children: [
|
|
183
|
-
/* @__PURE__ */ jsx(CoinsIcon, { className: colors2.accent }),
|
|
184
|
-
"Credit Balance"
|
|
185
|
-
] }),
|
|
186
|
-
/* @__PURE__ */ jsxs(CardDescription, { children: [
|
|
187
|
-
formatCredits(balance.available),
|
|
188
|
-
" credits remaining"
|
|
189
|
-
] })
|
|
190
|
-
] }),
|
|
191
|
-
/* @__PURE__ */ jsxs(CardContent, { className: "space-y-4", children: [
|
|
192
|
-
/* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
193
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between text-sm", children: [
|
|
194
|
-
/* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: "Used" }),
|
|
195
|
-
/* @__PURE__ */ jsx("span", { className: "font-medium", children: formatCredits(balance.used) })
|
|
196
|
-
] }),
|
|
197
|
-
/* @__PURE__ */ jsx(Progress, { value: usagePercent, variant, className: "h-3" }),
|
|
198
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between text-sm", children: [
|
|
199
|
-
/* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: "Available" }),
|
|
200
|
-
/* @__PURE__ */ jsx("span", { className: cn("font-medium", colors2.accent), children: formatCredits(balance.available) })
|
|
201
|
-
] })
|
|
202
|
-
] }),
|
|
203
|
-
/* @__PURE__ */ jsx(Button, { variant, className: "w-full", onClick: onAddCredits, children: "Add Credits" })
|
|
204
|
-
] })
|
|
205
|
-
] }),
|
|
206
|
-
/* @__PURE__ */ jsxs(Card, { variant, className: cn("lg:col-span-1", cardClassName), children: [
|
|
207
|
-
/* @__PURE__ */ jsxs(CardHeader, { children: [
|
|
208
|
-
/* @__PURE__ */ jsxs(CardTitle, { className: "flex items-center gap-2 text-base", children: [
|
|
209
|
-
/* @__PURE__ */ jsx(ChartIcon, { className: colors2.accent }),
|
|
210
|
-
"Usage Breakdown"
|
|
211
|
-
] }),
|
|
212
|
-
/* @__PURE__ */ jsx(CardDescription, { children: usage.period })
|
|
213
|
-
] }),
|
|
214
|
-
/* @__PURE__ */ jsxs(CardContent, { className: "space-y-4", children: [
|
|
215
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-baseline justify-between", children: [
|
|
216
|
-
/* @__PURE__ */ jsx("span", { className: "text-muted-foreground text-sm", children: "Total Usage" }),
|
|
217
|
-
/* @__PURE__ */ jsx("span", { className: cn("font-bold text-2xl", colors2.accent), children: formatCredits(usage.total) })
|
|
218
|
-
] }),
|
|
219
|
-
/* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
|
|
220
|
-
/* @__PURE__ */ jsx("p", { className: "font-medium text-muted-foreground text-xs uppercase tracking-wider", children: "By Model" }),
|
|
221
|
-
/* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
222
|
-
sortedModels.slice(0, 5).map(([model, credits]) => {
|
|
223
|
-
const modelPercent = usage.total > 0 ? credits / usage.total * 100 : 0;
|
|
224
|
-
return /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
|
|
225
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between text-sm", children: [
|
|
226
|
-
/* @__PURE__ */ jsx("span", { className: "truncate text-muted-foreground", children: model }),
|
|
227
|
-
/* @__PURE__ */ jsx("span", { className: "ml-2 font-medium", children: formatCredits(credits) })
|
|
228
|
-
] }),
|
|
229
|
-
/* @__PURE__ */ jsx("div", { className: "h-1.5 w-full overflow-hidden rounded-full bg-muted", children: /* @__PURE__ */ jsx(
|
|
230
|
-
"div",
|
|
231
|
-
{
|
|
232
|
-
className: cn(
|
|
233
|
-
"h-full rounded-full transition-all",
|
|
234
|
-
variant === "sandbox" && colors2.progress
|
|
235
|
-
),
|
|
236
|
-
style: { width: `${modelPercent}%` }
|
|
237
|
-
}
|
|
238
|
-
) })
|
|
239
|
-
] }, model);
|
|
240
|
-
}),
|
|
241
|
-
sortedModels.length > 5 && /* @__PURE__ */ jsxs("p", { className: "text-muted-foreground text-xs", children: [
|
|
242
|
-
"+",
|
|
243
|
-
sortedModels.length - 5,
|
|
244
|
-
" more models"
|
|
245
|
-
] }),
|
|
246
|
-
sortedModels.length === 0 && /* @__PURE__ */ jsx("p", { className: "text-muted-foreground text-sm", children: "No usage this period" })
|
|
247
|
-
] })
|
|
248
|
-
] })
|
|
249
|
-
] })
|
|
250
|
-
] })
|
|
251
|
-
] });
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
// src/dashboard/pricing-page.tsx
|
|
255
|
-
import { Check, Zap } from "lucide-react";
|
|
256
|
-
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
257
|
-
function formatPrice(cents) {
|
|
258
|
-
if (!Number.isFinite(cents) || cents < 0) return "$0";
|
|
259
|
-
return cents % 100 === 0 ? `$${cents / 100}` : `$${(cents / 100).toFixed(2)}`;
|
|
260
|
-
}
|
|
261
|
-
function PricingPage({
|
|
262
|
-
tiers,
|
|
263
|
-
currentTierId,
|
|
264
|
-
billingPeriod,
|
|
265
|
-
onBillingPeriodChange,
|
|
266
|
-
onSelectTier,
|
|
267
|
-
loading = false,
|
|
268
|
-
className
|
|
269
|
-
}) {
|
|
270
|
-
const tiersWithRecommended = tiers.map((tier, i) => ({
|
|
271
|
-
...tier,
|
|
272
|
-
recommended: tier.recommended ?? (tiers.length === 3 && i === 1)
|
|
273
|
-
}));
|
|
274
|
-
return /* @__PURE__ */ jsxs2("div", { className: cn("w-full space-y-10", className), children: [
|
|
275
|
-
/* @__PURE__ */ jsx2("div", { className: "flex justify-center", children: /* @__PURE__ */ jsxs2("div", { className: "inline-flex items-center rounded-full border border-border bg-muted/50 p-1", children: [
|
|
276
|
-
/* @__PURE__ */ jsx2(
|
|
277
|
-
"button",
|
|
278
|
-
{
|
|
279
|
-
type: "button",
|
|
280
|
-
onClick: () => onBillingPeriodChange("monthly"),
|
|
281
|
-
className: cn(
|
|
282
|
-
"rounded-full px-5 py-2 text-sm font-medium transition-all",
|
|
283
|
-
billingPeriod === "monthly" ? "bg-card text-foreground shadow-sm" : "text-muted-foreground hover:text-foreground"
|
|
284
|
-
),
|
|
285
|
-
children: "Monthly"
|
|
286
|
-
}
|
|
287
|
-
),
|
|
288
|
-
/* @__PURE__ */ jsxs2(
|
|
289
|
-
"button",
|
|
290
|
-
{
|
|
291
|
-
type: "button",
|
|
292
|
-
onClick: () => onBillingPeriodChange("yearly"),
|
|
293
|
-
className: cn(
|
|
294
|
-
"rounded-full px-5 py-2 text-sm font-medium transition-all",
|
|
295
|
-
billingPeriod === "yearly" ? "bg-card text-foreground shadow-sm" : "text-muted-foreground hover:text-foreground"
|
|
296
|
-
),
|
|
297
|
-
children: [
|
|
298
|
-
"Yearly",
|
|
299
|
-
/* @__PURE__ */ jsx2("span", { className: "ml-2 rounded-full bg-[var(--surface-success-bg)] px-2 py-0.5 text-[10px] font-bold text-[var(--surface-success-text)]", children: "Save 20%" })
|
|
300
|
-
]
|
|
301
|
-
}
|
|
302
|
-
)
|
|
303
|
-
] }) }),
|
|
304
|
-
/* @__PURE__ */ jsx2("div", { className: "grid grid-cols-1 gap-6 lg:grid-cols-3 items-start", children: tiersWithRecommended.map((tier) => {
|
|
305
|
-
const isCurrentTier = tier.id === currentTierId;
|
|
306
|
-
const isRecommended = tier.recommended;
|
|
307
|
-
const isFree = tier.monthlyPriceCents === 0;
|
|
308
|
-
const price = billingPeriod === "yearly" && tier.yearlyPriceCents !== void 0 ? tier.yearlyPriceCents : tier.monthlyPriceCents;
|
|
309
|
-
const displayPrice = billingPeriod === "yearly" ? Math.round(price / 12) : price;
|
|
310
|
-
return /* @__PURE__ */ jsxs2(
|
|
311
|
-
"div",
|
|
312
|
-
{
|
|
313
|
-
className: cn(
|
|
314
|
-
"relative flex flex-col rounded-2xl border transition-all",
|
|
315
|
-
isRecommended ? "border-primary shadow-[var(--shadow-glow)] scale-[1.02] z-10" : "border-border hover:border-primary/30"
|
|
316
|
-
),
|
|
317
|
-
children: [
|
|
318
|
-
isRecommended && /* @__PURE__ */ jsx2("div", { className: "absolute -top-4 left-1/2 -translate-x-1/2", children: /* @__PURE__ */ jsxs2("span", { 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", children: [
|
|
319
|
-
/* @__PURE__ */ jsx2(Zap, { className: "h-3 w-3" }),
|
|
320
|
-
"Most Popular"
|
|
321
|
-
] }) }),
|
|
322
|
-
isCurrentTier && !isRecommended && /* @__PURE__ */ jsx2("div", { className: "absolute -top-4 left-1/2 -translate-x-1/2", children: /* @__PURE__ */ jsx2("span", { className: "inline-flex items-center rounded-full bg-muted border border-border px-4 py-1.5 text-xs font-bold text-foreground", children: "Current Plan" }) }),
|
|
323
|
-
/* @__PURE__ */ jsxs2("div", { className: cn("flex flex-col p-8", isRecommended && "pt-10"), children: [
|
|
324
|
-
/* @__PURE__ */ jsxs2("div", { className: "mb-6", children: [
|
|
325
|
-
/* @__PURE__ */ jsx2("h3", { className: "text-lg font-bold text-foreground", children: tier.name }),
|
|
326
|
-
/* @__PURE__ */ jsx2("p", { className: "mt-1 text-sm text-muted-foreground", children: tier.description })
|
|
327
|
-
] }),
|
|
328
|
-
/* @__PURE__ */ jsxs2("div", { className: "mb-8", children: [
|
|
329
|
-
/* @__PURE__ */ jsxs2("div", { className: "flex items-baseline gap-1", children: [
|
|
330
|
-
/* @__PURE__ */ jsx2("span", { className: cn("text-5xl font-extrabold tracking-tight", isRecommended ? "text-primary" : "text-foreground"), children: isFree ? "Free" : formatPrice(displayPrice) }),
|
|
331
|
-
!isFree && /* @__PURE__ */ jsx2("span", { className: "text-muted-foreground text-sm font-medium", children: "/mo" })
|
|
332
|
-
] }),
|
|
333
|
-
billingPeriod === "yearly" && tier.yearlyPriceCents !== void 0 && !isFree && /* @__PURE__ */ jsxs2("p", { className: "mt-1 text-xs text-muted-foreground", children: [
|
|
334
|
-
formatPrice(tier.yearlyPriceCents),
|
|
335
|
-
" billed annually"
|
|
336
|
-
] })
|
|
337
|
-
] }),
|
|
338
|
-
/* @__PURE__ */ jsx2(
|
|
339
|
-
"button",
|
|
340
|
-
{
|
|
341
|
-
type: "button",
|
|
342
|
-
onClick: () => onSelectTier(tier.id),
|
|
343
|
-
disabled: isCurrentTier || loading,
|
|
344
|
-
className: cn(
|
|
345
|
-
"w-full rounded-xl py-3 text-sm font-bold transition-all active:scale-[0.98] disabled:opacity-50",
|
|
346
|
-
isRecommended ? "bg-primary text-primary-foreground hover:bg-primary/90 shadow-sm" : isCurrentTier ? "bg-muted text-muted-foreground border border-border cursor-default" : "bg-card text-foreground border border-border hover:border-primary/50 hover:bg-muted"
|
|
347
|
-
),
|
|
348
|
-
children: isCurrentTier ? "Current Plan" : isFree ? "Get Started" : "Subscribe"
|
|
349
|
-
}
|
|
350
|
-
),
|
|
351
|
-
/* @__PURE__ */ jsx2("div", { className: "my-8 border-t border-border" }),
|
|
352
|
-
/* @__PURE__ */ jsx2("ul", { className: "space-y-3.5 flex-1", children: tier.features.map((feature) => /* @__PURE__ */ jsxs2("li", { className: "flex items-start gap-3", children: [
|
|
353
|
-
/* @__PURE__ */ jsx2("div", { className: cn(
|
|
354
|
-
"mt-0.5 flex h-5 w-5 shrink-0 items-center justify-center rounded-full",
|
|
355
|
-
isRecommended ? "bg-primary/10 text-primary" : "bg-muted text-muted-foreground"
|
|
356
|
-
), children: /* @__PURE__ */ jsx2(Check, { className: "h-3 w-3" }) }),
|
|
357
|
-
/* @__PURE__ */ jsx2("span", { className: "text-sm text-foreground/80", children: feature })
|
|
358
|
-
] }, feature)) })
|
|
359
|
-
] })
|
|
360
|
-
]
|
|
361
|
-
},
|
|
362
|
-
tier.id
|
|
363
|
-
);
|
|
364
|
-
}) })
|
|
365
|
-
] });
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
// src/dashboard/usage-chart.tsx
|
|
369
|
-
import * as React from "react";
|
|
370
|
-
import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
371
|
-
var colors = {
|
|
372
|
-
bar: "bg-[image:var(--accent-gradient-strong)]",
|
|
373
|
-
barHover: "hover:brightness-110",
|
|
374
|
-
text: "text-[var(--accent-text)]"
|
|
375
|
-
};
|
|
376
|
-
function formatDate2(dateStr) {
|
|
377
|
-
const date = new Date(dateStr);
|
|
378
|
-
return date.toLocaleDateString("en-US", { month: "short", day: "numeric" });
|
|
379
|
-
}
|
|
380
|
-
function formatValue(value) {
|
|
381
|
-
if (value >= 1e6) {
|
|
382
|
-
return `${(value / 1e6).toFixed(1)}M`;
|
|
383
|
-
}
|
|
384
|
-
if (value >= 1e3) {
|
|
385
|
-
return `${(value / 1e3).toFixed(1)}K`;
|
|
386
|
-
}
|
|
387
|
-
return value.toLocaleString();
|
|
388
|
-
}
|
|
389
|
-
function UsageChart({ data, title, unit, className }) {
|
|
390
|
-
const maxValue = Math.max(...data.map((d) => d.value), 1);
|
|
391
|
-
const total = data.reduce((sum, d) => sum + d.value, 0);
|
|
392
|
-
const [hoveredIndex, setHoveredIndex] = React.useState(null);
|
|
393
|
-
return /* @__PURE__ */ jsxs3(Card, { className, children: [
|
|
394
|
-
/* @__PURE__ */ jsxs3(CardHeader, { className: "flex flex-row items-center justify-between pb-2", children: [
|
|
395
|
-
/* @__PURE__ */ jsx3(CardTitle, { className: "font-medium text-base", children: title }),
|
|
396
|
-
/* @__PURE__ */ jsxs3("div", { className: "text-right", children: [
|
|
397
|
-
/* @__PURE__ */ jsx3("span", { className: cn("font-bold text-2xl", colors.text), children: formatValue(total) }),
|
|
398
|
-
/* @__PURE__ */ jsx3("span", { className: "ml-1 text-muted-foreground text-sm", children: unit })
|
|
399
|
-
] })
|
|
400
|
-
] }),
|
|
401
|
-
/* @__PURE__ */ jsxs3(CardContent, { children: [
|
|
402
|
-
/* @__PURE__ */ jsxs3("div", { className: "relative", children: [
|
|
403
|
-
/* @__PURE__ */ jsxs3("div", { className: "absolute top-0 left-0 flex h-48 flex-col justify-between text-muted-foreground text-xs", children: [
|
|
404
|
-
/* @__PURE__ */ jsx3("span", { children: formatValue(maxValue) }),
|
|
405
|
-
/* @__PURE__ */ jsx3("span", { children: formatValue(Math.round(maxValue / 2)) }),
|
|
406
|
-
/* @__PURE__ */ jsx3("span", { children: "0" })
|
|
407
|
-
] }),
|
|
408
|
-
/* @__PURE__ */ jsx3("div", { className: "ml-10 flex h-48 items-end gap-1", children: data.map((point, index) => {
|
|
409
|
-
const heightPercent = point.value / maxValue * 100;
|
|
410
|
-
const isHovered = hoveredIndex === index;
|
|
411
|
-
return (
|
|
412
|
-
// biome-ignore lint/a11y/noStaticElementInteractions: chart bar uses hover for tooltip display
|
|
413
|
-
/* @__PURE__ */ jsxs3(
|
|
414
|
-
"div",
|
|
415
|
-
{
|
|
416
|
-
className: "group relative flex flex-1 flex-col items-center",
|
|
417
|
-
onMouseEnter: () => setHoveredIndex(index),
|
|
418
|
-
onMouseLeave: () => setHoveredIndex(null),
|
|
419
|
-
children: [
|
|
420
|
-
isHovered && /* @__PURE__ */ jsxs3("div", { className: "absolute -top-12 z-10 rounded-lg bg-popover px-3 py-1.5 text-sm shadow-lg", children: [
|
|
421
|
-
/* @__PURE__ */ jsxs3("p", { className: "font-medium", children: [
|
|
422
|
-
formatValue(point.value),
|
|
423
|
-
" ",
|
|
424
|
-
unit
|
|
425
|
-
] }),
|
|
426
|
-
/* @__PURE__ */ jsx3("p", { className: "text-muted-foreground text-xs", children: formatDate2(point.date) })
|
|
427
|
-
] }),
|
|
428
|
-
/* @__PURE__ */ jsx3(
|
|
429
|
-
"div",
|
|
430
|
-
{
|
|
431
|
-
className: cn(
|
|
432
|
-
"min-h-[2px] w-full rounded-t-sm transition-all duration-200",
|
|
433
|
-
colors.bar,
|
|
434
|
-
colors.barHover,
|
|
435
|
-
isHovered && "opacity-80"
|
|
436
|
-
),
|
|
437
|
-
style: { height: `${Math.max(heightPercent, 1)}%` }
|
|
438
|
-
}
|
|
439
|
-
)
|
|
440
|
-
]
|
|
441
|
-
},
|
|
442
|
-
point.date
|
|
443
|
-
)
|
|
444
|
-
);
|
|
445
|
-
}) }),
|
|
446
|
-
/* @__PURE__ */ jsx3("div", { className: "mt-2 ml-10 flex gap-1", children: data.map((point, index) => /* @__PURE__ */ jsx3(
|
|
447
|
-
"div",
|
|
448
|
-
{
|
|
449
|
-
className: cn(
|
|
450
|
-
"flex-1 truncate text-center text-muted-foreground text-xs",
|
|
451
|
-
hoveredIndex === index && colors.text
|
|
452
|
-
),
|
|
453
|
-
children: data.length <= 7 || index % Math.ceil(data.length / 7) === 0 ? formatDate2(point.date) : ""
|
|
454
|
-
},
|
|
455
|
-
point.date
|
|
456
|
-
)) })
|
|
457
|
-
] }),
|
|
458
|
-
/* @__PURE__ */ jsxs3("div", { className: "mt-4 grid grid-cols-3 gap-4 border-border border-t pt-4", children: [
|
|
459
|
-
/* @__PURE__ */ jsxs3("div", { className: "text-center", children: [
|
|
460
|
-
/* @__PURE__ */ jsx3("p", { className: "text-muted-foreground text-xs", children: "Average" }),
|
|
461
|
-
/* @__PURE__ */ jsxs3("p", { className: "font-medium", children: [
|
|
462
|
-
formatValue(Math.round(total / data.length)),
|
|
463
|
-
" ",
|
|
464
|
-
unit
|
|
465
|
-
] })
|
|
466
|
-
] }),
|
|
467
|
-
/* @__PURE__ */ jsxs3("div", { className: "text-center", children: [
|
|
468
|
-
/* @__PURE__ */ jsx3("p", { className: "text-muted-foreground text-xs", children: "Peak" }),
|
|
469
|
-
/* @__PURE__ */ jsxs3("p", { className: "font-medium", children: [
|
|
470
|
-
formatValue(maxValue),
|
|
471
|
-
" ",
|
|
472
|
-
unit
|
|
473
|
-
] })
|
|
474
|
-
] }),
|
|
475
|
-
/* @__PURE__ */ jsxs3("div", { className: "text-center", children: [
|
|
476
|
-
/* @__PURE__ */ jsx3("p", { className: "text-muted-foreground text-xs", children: "Total" }),
|
|
477
|
-
/* @__PURE__ */ jsxs3("p", { className: cn("font-medium", colors.text), children: [
|
|
478
|
-
formatValue(total),
|
|
479
|
-
" ",
|
|
480
|
-
unit
|
|
481
|
-
] })
|
|
482
|
-
] })
|
|
483
|
-
] })
|
|
484
|
-
] })
|
|
485
|
-
] });
|
|
486
|
-
}
|
|
487
|
-
|
|
488
|
-
export {
|
|
489
|
-
BillingDashboard,
|
|
490
|
-
formatPrice,
|
|
491
|
-
PricingPage,
|
|
492
|
-
UsageChart
|
|
493
|
-
};
|