@ai-billing/nextjs 0.0.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.
- package/LICENSE +201 -0
- package/README.md +50 -0
- package/dist/index.cjs +36 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +4 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/polar/CreditTopUpPolar.cjs +278 -0
- package/dist/polar/CreditTopUpPolar.cjs.map +1 -0
- package/dist/polar/CreditTopUpPolar.d.cts +9 -0
- package/dist/polar/CreditTopUpPolar.d.ts +9 -0
- package/dist/polar/CreditTopUpPolar.js +244 -0
- package/dist/polar/CreditTopUpPolar.js.map +1 -0
- package/dist/polar/CreditUsagePolar.cjs +133 -0
- package/dist/polar/CreditUsagePolar.cjs.map +1 -0
- package/dist/polar/CreditUsagePolar.d.cts +10 -0
- package/dist/polar/CreditUsagePolar.d.ts +10 -0
- package/dist/polar/CreditUsagePolar.js +107 -0
- package/dist/polar/CreditUsagePolar.js.map +1 -0
- package/dist/polar/createCheckout.cjs +47 -0
- package/dist/polar/createCheckout.cjs.map +1 -0
- package/dist/polar/createCheckout.d.cts +9 -0
- package/dist/polar/createCheckout.d.ts +9 -0
- package/dist/polar/createCheckout.js +23 -0
- package/dist/polar/createCheckout.js.map +1 -0
- package/dist/polar/fetchPolarConfig.cjs +52 -0
- package/dist/polar/fetchPolarConfig.cjs.map +1 -0
- package/dist/polar/fetchPolarConfig.d.cts +6 -0
- package/dist/polar/fetchPolarConfig.d.ts +6 -0
- package/dist/polar/fetchPolarConfig.js +28 -0
- package/dist/polar/fetchPolarConfig.js.map +1 -0
- package/dist/polar/fetchPolarUsage.cjs +64 -0
- package/dist/polar/fetchPolarUsage.cjs.map +1 -0
- package/dist/polar/fetchPolarUsage.d.cts +9 -0
- package/dist/polar/fetchPolarUsage.d.ts +9 -0
- package/dist/polar/fetchPolarUsage.js +40 -0
- package/dist/polar/fetchPolarUsage.js.map +1 -0
- package/dist/polar/fetchTopUpConfig.cjs +55 -0
- package/dist/polar/fetchTopUpConfig.cjs.map +1 -0
- package/dist/polar/fetchTopUpConfig.d.cts +10 -0
- package/dist/polar/fetchTopUpConfig.d.ts +10 -0
- package/dist/polar/fetchTopUpConfig.js +31 -0
- package/dist/polar/fetchTopUpConfig.js.map +1 -0
- package/dist/polar/types.cjs +17 -0
- package/dist/polar/types.cjs.map +1 -0
- package/dist/polar/types.d.cts +18 -0
- package/dist/polar/types.d.ts +18 -0
- package/dist/polar/types.js +1 -0
- package/dist/polar/types.js.map +1 -0
- package/dist/server.cjs +44 -0
- package/dist/server.cjs.map +1 -0
- package/dist/server.d.cts +8 -0
- package/dist/server.d.ts +8 -0
- package/dist/server.js +15 -0
- package/dist/server.js.map +1 -0
- package/dist/stripe/CreditUsageStripe.cjs +158 -0
- package/dist/stripe/CreditUsageStripe.cjs.map +1 -0
- package/dist/stripe/CreditUsageStripe.d.cts +11 -0
- package/dist/stripe/CreditUsageStripe.d.ts +11 -0
- package/dist/stripe/CreditUsageStripe.js +132 -0
- package/dist/stripe/CreditUsageStripe.js.map +1 -0
- package/dist/stripe/fetchStripeConfig.cjs +52 -0
- package/dist/stripe/fetchStripeConfig.cjs.map +1 -0
- package/dist/stripe/fetchStripeConfig.d.cts +6 -0
- package/dist/stripe/fetchStripeConfig.d.ts +6 -0
- package/dist/stripe/fetchStripeConfig.js +28 -0
- package/dist/stripe/fetchStripeConfig.js.map +1 -0
- package/dist/stripe/fetchStripeUsage.cjs +67 -0
- package/dist/stripe/fetchStripeUsage.cjs.map +1 -0
- package/dist/stripe/fetchStripeUsage.d.cts +9 -0
- package/dist/stripe/fetchStripeUsage.d.ts +9 -0
- package/dist/stripe/fetchStripeUsage.js +33 -0
- package/dist/stripe/fetchStripeUsage.js.map +1 -0
- package/dist/stripe/types.cjs +17 -0
- package/dist/stripe/types.cjs.map +1 -0
- package/dist/stripe/types.d.cts +9 -0
- package/dist/stripe/types.d.ts +9 -0
- package/dist/stripe/types.js +1 -0
- package/dist/stripe/types.js.map +1 -0
- package/dist/styles.cjs +83 -0
- package/dist/styles.cjs.map +1 -0
- package/dist/styles.d.cts +11 -0
- package/dist/styles.d.ts +11 -0
- package/dist/styles.js +53 -0
- package/dist/styles.js.map +1 -0
- package/dist/utils.cjs +53 -0
- package/dist/utils.cjs.map +1 -0
- package/dist/utils.d.cts +20 -0
- package/dist/utils.d.ts +20 -0
- package/dist/utils.js +26 -0
- package/dist/utils.js.map +1 -0
- package/package.json +82 -0
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import React, { useState, useEffect, useTransition } from "react";
|
|
4
|
+
import { cardBase, mutedText } from "../styles.js";
|
|
5
|
+
import { formatCents, taxMessages } from "../utils.js";
|
|
6
|
+
import { createCheckout as checkoutAction } from "./createCheckout.js";
|
|
7
|
+
import { fetchTopUpConfig } from "./fetchTopUpConfig.js";
|
|
8
|
+
function LightningIcon({ selected }) {
|
|
9
|
+
return /* @__PURE__ */ jsx(
|
|
10
|
+
"div",
|
|
11
|
+
{
|
|
12
|
+
style: {
|
|
13
|
+
width: 36,
|
|
14
|
+
height: 36,
|
|
15
|
+
borderRadius: 10,
|
|
16
|
+
display: "flex",
|
|
17
|
+
alignItems: "center",
|
|
18
|
+
justifyContent: "center",
|
|
19
|
+
flexShrink: 0,
|
|
20
|
+
transition: "background 0.15s",
|
|
21
|
+
background: selected ? "var(--foreground)" : "var(--muted)"
|
|
22
|
+
},
|
|
23
|
+
children: /* @__PURE__ */ jsx("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ jsx(
|
|
24
|
+
"path",
|
|
25
|
+
{
|
|
26
|
+
d: "M13 2L4.5 13.5H11L10 22L20.5 10.5H14L13 2Z",
|
|
27
|
+
fill: selected ? "var(--background)" : "var(--muted-foreground)",
|
|
28
|
+
stroke: selected ? "var(--background)" : "var(--muted-foreground)",
|
|
29
|
+
strokeWidth: "0.5",
|
|
30
|
+
strokeLinejoin: "round"
|
|
31
|
+
}
|
|
32
|
+
) })
|
|
33
|
+
}
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
const CreditTopUpPolar = React.forwardRef(
|
|
37
|
+
({
|
|
38
|
+
userId,
|
|
39
|
+
title = "Choose a credit bundle to top up your workspace balance.",
|
|
40
|
+
className,
|
|
41
|
+
style,
|
|
42
|
+
...props
|
|
43
|
+
}, ref) => {
|
|
44
|
+
const cls = (className ?? "").trim();
|
|
45
|
+
const [packages, setPackages] = useState([]);
|
|
46
|
+
const [taxBehavior, setTaxBehavior] = useState();
|
|
47
|
+
const [loading, setLoading] = useState(true);
|
|
48
|
+
const [selectedIdx, setSelectedIdx] = useState(0);
|
|
49
|
+
const [isPending, startTransition] = useTransition();
|
|
50
|
+
const [error, setError] = useState(null);
|
|
51
|
+
useEffect(() => {
|
|
52
|
+
let cancelled = false;
|
|
53
|
+
setLoading(true);
|
|
54
|
+
(async () => {
|
|
55
|
+
try {
|
|
56
|
+
const config = await fetchTopUpConfig();
|
|
57
|
+
if (cancelled) return;
|
|
58
|
+
setPackages(config.packages);
|
|
59
|
+
if (config.taxBehavior) setTaxBehavior(config.taxBehavior);
|
|
60
|
+
} catch {
|
|
61
|
+
} finally {
|
|
62
|
+
if (!cancelled) setLoading(false);
|
|
63
|
+
}
|
|
64
|
+
})();
|
|
65
|
+
return () => {
|
|
66
|
+
cancelled = true;
|
|
67
|
+
};
|
|
68
|
+
}, []);
|
|
69
|
+
const selected = packages[selectedIdx] ?? null;
|
|
70
|
+
function handlePurchase() {
|
|
71
|
+
if (!selected) return;
|
|
72
|
+
setError(null);
|
|
73
|
+
startTransition(async () => {
|
|
74
|
+
try {
|
|
75
|
+
const url = await checkoutAction(
|
|
76
|
+
selected.id,
|
|
77
|
+
userId,
|
|
78
|
+
window.location.origin
|
|
79
|
+
);
|
|
80
|
+
window.location.href = url;
|
|
81
|
+
} catch (e) {
|
|
82
|
+
setError(String(e));
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
if (loading) {
|
|
87
|
+
return /* @__PURE__ */ jsx(
|
|
88
|
+
"div",
|
|
89
|
+
{
|
|
90
|
+
ref,
|
|
91
|
+
className: cls,
|
|
92
|
+
style: { ...cardBase, height: 120, opacity: 0.5, ...style },
|
|
93
|
+
...props
|
|
94
|
+
}
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
if (packages.length === 0) {
|
|
98
|
+
return /* @__PURE__ */ jsx(
|
|
99
|
+
"div",
|
|
100
|
+
{
|
|
101
|
+
ref,
|
|
102
|
+
className: cls,
|
|
103
|
+
style: { ...cardBase, ...style },
|
|
104
|
+
...props,
|
|
105
|
+
children: /* @__PURE__ */ jsx("p", { style: mutedText, children: "No top-up packages available." })
|
|
106
|
+
}
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
return /* @__PURE__ */ jsxs(
|
|
110
|
+
"div",
|
|
111
|
+
{
|
|
112
|
+
ref,
|
|
113
|
+
className: cls,
|
|
114
|
+
style: {
|
|
115
|
+
...cardBase,
|
|
116
|
+
display: "flex",
|
|
117
|
+
flexDirection: "column",
|
|
118
|
+
...style
|
|
119
|
+
},
|
|
120
|
+
...props,
|
|
121
|
+
children: [
|
|
122
|
+
title && /* @__PURE__ */ jsx("p", { style: { ...mutedText, marginBottom: 12 }, children: title }),
|
|
123
|
+
/* @__PURE__ */ jsx("div", { style: { display: "flex", flexDirection: "column", gap: 6 }, children: packages.map((pkg, i) => {
|
|
124
|
+
const isSelected = i === selectedIdx;
|
|
125
|
+
return /* @__PURE__ */ jsxs(
|
|
126
|
+
"div",
|
|
127
|
+
{
|
|
128
|
+
role: "button",
|
|
129
|
+
tabIndex: 0,
|
|
130
|
+
onClick: () => setSelectedIdx(i),
|
|
131
|
+
onKeyDown: (e) => (e.key === "Enter" || e.key === " ") && setSelectedIdx(i),
|
|
132
|
+
style: {
|
|
133
|
+
display: "flex",
|
|
134
|
+
alignItems: "center",
|
|
135
|
+
gap: 12,
|
|
136
|
+
padding: "10px 14px",
|
|
137
|
+
borderRadius: "var(--radius, 0.75rem)",
|
|
138
|
+
background: isSelected ? "var(--muted)" : "transparent",
|
|
139
|
+
border: isSelected ? "1px solid var(--border)" : "1px solid transparent",
|
|
140
|
+
cursor: "pointer",
|
|
141
|
+
transition: "background 0.15s, border-color 0.15s",
|
|
142
|
+
userSelect: "none",
|
|
143
|
+
outline: "none"
|
|
144
|
+
},
|
|
145
|
+
children: [
|
|
146
|
+
/* @__PURE__ */ jsx(LightningIcon, { selected: isSelected }),
|
|
147
|
+
/* @__PURE__ */ jsx("div", { style: { flex: 1, minWidth: 0 }, children: /* @__PURE__ */ jsxs(
|
|
148
|
+
"p",
|
|
149
|
+
{
|
|
150
|
+
style: {
|
|
151
|
+
margin: 0,
|
|
152
|
+
fontSize: 14,
|
|
153
|
+
fontWeight: 600,
|
|
154
|
+
color: "var(--card-foreground)",
|
|
155
|
+
lineHeight: 1.3
|
|
156
|
+
},
|
|
157
|
+
children: [
|
|
158
|
+
"Top-up ",
|
|
159
|
+
formatCents(pkg.priceCents)
|
|
160
|
+
]
|
|
161
|
+
}
|
|
162
|
+
) }),
|
|
163
|
+
/* @__PURE__ */ jsx(
|
|
164
|
+
"span",
|
|
165
|
+
{
|
|
166
|
+
style: {
|
|
167
|
+
flexShrink: 0,
|
|
168
|
+
fontSize: 16,
|
|
169
|
+
fontWeight: 700,
|
|
170
|
+
color: "var(--card-foreground)"
|
|
171
|
+
},
|
|
172
|
+
children: formatCents(pkg.priceCents)
|
|
173
|
+
}
|
|
174
|
+
)
|
|
175
|
+
]
|
|
176
|
+
},
|
|
177
|
+
pkg.id
|
|
178
|
+
);
|
|
179
|
+
}) }),
|
|
180
|
+
/* @__PURE__ */ jsxs("div", { style: { marginTop: 20 }, children: [
|
|
181
|
+
/* @__PURE__ */ jsx(
|
|
182
|
+
"button",
|
|
183
|
+
{
|
|
184
|
+
type: "button",
|
|
185
|
+
disabled: isPending || !selected,
|
|
186
|
+
onClick: handlePurchase,
|
|
187
|
+
style: {
|
|
188
|
+
fontFamily: "inherit",
|
|
189
|
+
width: "100%",
|
|
190
|
+
height: 38,
|
|
191
|
+
borderRadius: "var(--radius, 0.5rem)",
|
|
192
|
+
background: "var(--primary)",
|
|
193
|
+
color: "var(--primary-foreground)",
|
|
194
|
+
border: 0,
|
|
195
|
+
fontSize: 14,
|
|
196
|
+
fontWeight: 500,
|
|
197
|
+
cursor: isPending || !selected ? "not-allowed" : "pointer",
|
|
198
|
+
opacity: isPending ? 0.6 : 1,
|
|
199
|
+
display: "flex",
|
|
200
|
+
alignItems: "center",
|
|
201
|
+
justifyContent: "center",
|
|
202
|
+
transition: "opacity 0.15s"
|
|
203
|
+
},
|
|
204
|
+
children: isPending ? "Processing\u2026" : selected ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
205
|
+
"Top-up ",
|
|
206
|
+
formatCents(selected.priceCents)
|
|
207
|
+
] }) : "Select a package"
|
|
208
|
+
}
|
|
209
|
+
),
|
|
210
|
+
error && /* @__PURE__ */ jsx(
|
|
211
|
+
"p",
|
|
212
|
+
{
|
|
213
|
+
style: {
|
|
214
|
+
marginTop: 8,
|
|
215
|
+
fontSize: 12,
|
|
216
|
+
color: "#ef4444",
|
|
217
|
+
textAlign: "center"
|
|
218
|
+
},
|
|
219
|
+
children: error
|
|
220
|
+
}
|
|
221
|
+
)
|
|
222
|
+
] }),
|
|
223
|
+
taxBehavior && /* @__PURE__ */ jsx(
|
|
224
|
+
"p",
|
|
225
|
+
{
|
|
226
|
+
style: {
|
|
227
|
+
marginTop: 14,
|
|
228
|
+
fontSize: 11,
|
|
229
|
+
color: "var(--muted-foreground)",
|
|
230
|
+
textAlign: "center"
|
|
231
|
+
},
|
|
232
|
+
children: taxMessages[taxBehavior]
|
|
233
|
+
}
|
|
234
|
+
)
|
|
235
|
+
]
|
|
236
|
+
}
|
|
237
|
+
);
|
|
238
|
+
}
|
|
239
|
+
);
|
|
240
|
+
CreditTopUpPolar.displayName = "CreditTopUpPolar";
|
|
241
|
+
export {
|
|
242
|
+
CreditTopUpPolar
|
|
243
|
+
};
|
|
244
|
+
//# sourceMappingURL=CreditTopUpPolar.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/polar/CreditTopUpPolar.tsx"],"sourcesContent":["'use client';\n\nimport React, { useState, useEffect, useTransition } from 'react';\nimport { cardBase, mutedText } from '../styles.js';\nimport { formatCents, taxMessages } from '../utils.js';\nimport { createCheckout as checkoutAction } from './createCheckout.js';\nimport { fetchTopUpConfig } from './fetchTopUpConfig.js';\nimport type { CreditPackage } from './types.js';\n\nexport interface CreditTopUpPolarProps extends React.HTMLAttributes<HTMLDivElement> {\n userId: string;\n title?: string;\n}\n\nfunction LightningIcon({ selected }: { selected: boolean }) {\n return (\n <div\n style={{\n width: 36,\n height: 36,\n borderRadius: 10,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n flexShrink: 0,\n transition: 'background 0.15s',\n background: selected ? 'var(--foreground)' : 'var(--muted)',\n }}\n >\n <svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\">\n <path\n d=\"M13 2L4.5 13.5H11L10 22L20.5 10.5H14L13 2Z\"\n fill={selected ? 'var(--background)' : 'var(--muted-foreground)'}\n stroke={selected ? 'var(--background)' : 'var(--muted-foreground)'}\n strokeWidth=\"0.5\"\n strokeLinejoin=\"round\"\n />\n </svg>\n </div>\n );\n}\n\nexport const CreditTopUpPolar = React.forwardRef<\n HTMLDivElement,\n CreditTopUpPolarProps\n>(\n (\n {\n userId,\n title = 'Choose a credit bundle to top up your workspace balance.',\n className,\n style,\n ...props\n },\n ref,\n ) => {\n const cls = (className ?? '').trim();\n const [packages, setPackages] = useState<CreditPackage[]>([]);\n const [taxBehavior, setTaxBehavior] = useState<\n 'inclusive' | 'exclusive' | 'location'\n >();\n const [loading, setLoading] = useState(true);\n const [selectedIdx, setSelectedIdx] = useState(0);\n const [isPending, startTransition] = useTransition();\n const [error, setError] = useState<string | null>(null);\n\n useEffect(() => {\n let cancelled = false;\n setLoading(true);\n (async () => {\n try {\n const config = await fetchTopUpConfig();\n if (cancelled) return;\n setPackages(config.packages);\n if (config.taxBehavior) setTaxBehavior(config.taxBehavior);\n } catch {\n /* no data */\n } finally {\n if (!cancelled) setLoading(false);\n }\n })();\n return () => {\n cancelled = true;\n };\n }, []);\n\n const selected = packages[selectedIdx] ?? null;\n\n function handlePurchase() {\n if (!selected) return;\n setError(null);\n startTransition(async () => {\n try {\n const url = await checkoutAction(\n selected.id,\n userId,\n window.location.origin,\n );\n window.location.href = url;\n } catch (e) {\n setError(String(e));\n }\n });\n }\n\n if (loading) {\n return (\n <div\n ref={ref}\n className={cls}\n style={{ ...cardBase, height: 120, opacity: 0.5, ...style }}\n {...props}\n />\n );\n }\n\n if (packages.length === 0) {\n return (\n <div\n ref={ref}\n className={cls}\n style={{ ...cardBase, ...style }}\n {...props}\n >\n <p style={mutedText}>No top-up packages available.</p>\n </div>\n );\n }\n\n return (\n <div\n ref={ref}\n className={cls}\n style={{\n ...cardBase,\n display: 'flex',\n flexDirection: 'column',\n ...style,\n }}\n {...props}\n >\n {title && <p style={{ ...mutedText, marginBottom: 12 }}>{title}</p>}\n\n <div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>\n {packages.map((pkg, i) => {\n const isSelected = i === selectedIdx;\n return (\n <div\n key={pkg.id}\n role=\"button\"\n tabIndex={0}\n onClick={() => setSelectedIdx(i)}\n onKeyDown={e =>\n (e.key === 'Enter' || e.key === ' ') && setSelectedIdx(i)\n }\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: 12,\n padding: '10px 14px',\n borderRadius: 'var(--radius, 0.75rem)',\n background: isSelected ? 'var(--muted)' : 'transparent',\n border: isSelected\n ? '1px solid var(--border)'\n : '1px solid transparent',\n cursor: 'pointer',\n transition: 'background 0.15s, border-color 0.15s',\n userSelect: 'none',\n outline: 'none',\n }}\n >\n <LightningIcon selected={isSelected} />\n <div style={{ flex: 1, minWidth: 0 }}>\n <p\n style={{\n margin: 0,\n fontSize: 14,\n fontWeight: 600,\n color: 'var(--card-foreground)',\n lineHeight: 1.3,\n }}\n >\n Top-up {formatCents(pkg.priceCents)}\n </p>\n </div>\n <span\n style={{\n flexShrink: 0,\n fontSize: 16,\n fontWeight: 700,\n color: 'var(--card-foreground)',\n }}\n >\n {formatCents(pkg.priceCents)}\n </span>\n </div>\n );\n })}\n </div>\n\n <div style={{ marginTop: 20 }}>\n <button\n type=\"button\"\n disabled={isPending || !selected}\n onClick={handlePurchase}\n style={{\n fontFamily: 'inherit',\n width: '100%',\n height: 38,\n borderRadius: 'var(--radius, 0.5rem)',\n background: 'var(--primary)',\n color: 'var(--primary-foreground)',\n border: 0,\n fontSize: 14,\n fontWeight: 500,\n cursor: isPending || !selected ? 'not-allowed' : 'pointer',\n opacity: isPending ? 0.6 : 1,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n transition: 'opacity 0.15s',\n }}\n >\n {isPending ? (\n 'Processing…'\n ) : selected ? (\n <>Top-up {formatCents(selected.priceCents)}</>\n ) : (\n 'Select a package'\n )}\n </button>\n {error && (\n <p\n style={{\n marginTop: 8,\n fontSize: 12,\n color: '#ef4444',\n textAlign: 'center',\n }}\n >\n {error}\n </p>\n )}\n </div>\n\n {taxBehavior && (\n <p\n style={{\n marginTop: 14,\n fontSize: 11,\n color: 'var(--muted-foreground)',\n textAlign: 'center',\n }}\n >\n {taxMessages[taxBehavior]}\n </p>\n )}\n </div>\n );\n },\n);\nCreditTopUpPolar.displayName = 'CreditTopUpPolar';\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
"use client";
|
|
3
|
+
var __create = Object.create;
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
8
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
|
+
var __export = (target, all) => {
|
|
10
|
+
for (var name in all)
|
|
11
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
12
|
+
};
|
|
13
|
+
var __copyProps = (to, from, except, desc) => {
|
|
14
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
15
|
+
for (let key of __getOwnPropNames(from))
|
|
16
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
17
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
18
|
+
}
|
|
19
|
+
return to;
|
|
20
|
+
};
|
|
21
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
22
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
23
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
24
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
25
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
26
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
27
|
+
mod
|
|
28
|
+
));
|
|
29
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
30
|
+
var CreditUsagePolar_exports = {};
|
|
31
|
+
__export(CreditUsagePolar_exports, {
|
|
32
|
+
CreditUsagePolar: () => CreditUsagePolar
|
|
33
|
+
});
|
|
34
|
+
module.exports = __toCommonJS(CreditUsagePolar_exports);
|
|
35
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
36
|
+
var import_react = __toESM(require("react"), 1);
|
|
37
|
+
var import_styles = require("../styles.js");
|
|
38
|
+
var import_utils = require("../utils.js");
|
|
39
|
+
var import_fetchPolarUsage = require("./fetchPolarUsage.js");
|
|
40
|
+
const CreditUsagePolar = import_react.default.forwardRef(({ userId, budget, label, className, style, ...props }, ref) => {
|
|
41
|
+
const cls = (className ?? "").trim();
|
|
42
|
+
const [data, setData] = (0, import_react.useState)(null);
|
|
43
|
+
const [loading, setLoading] = (0, import_react.useState)(true);
|
|
44
|
+
(0, import_react.useEffect)(() => {
|
|
45
|
+
let cancelled = false;
|
|
46
|
+
setLoading(true);
|
|
47
|
+
(async () => {
|
|
48
|
+
try {
|
|
49
|
+
const result = await (0, import_fetchPolarUsage.fetchPolarUsage)(userId);
|
|
50
|
+
if (!cancelled) setData(result);
|
|
51
|
+
} catch {
|
|
52
|
+
if (!cancelled) setData(null);
|
|
53
|
+
} finally {
|
|
54
|
+
if (!cancelled) setLoading(false);
|
|
55
|
+
}
|
|
56
|
+
})();
|
|
57
|
+
return () => {
|
|
58
|
+
cancelled = true;
|
|
59
|
+
};
|
|
60
|
+
}, [userId]);
|
|
61
|
+
if (loading) {
|
|
62
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
63
|
+
"div",
|
|
64
|
+
{
|
|
65
|
+
ref,
|
|
66
|
+
className: cls,
|
|
67
|
+
style: { ...import_styles.cardBase, height: 120, opacity: 0.5, ...style },
|
|
68
|
+
...props
|
|
69
|
+
}
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
if (!data?.found) {
|
|
73
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
74
|
+
"div",
|
|
75
|
+
{
|
|
76
|
+
ref,
|
|
77
|
+
className: cls,
|
|
78
|
+
style: { ...import_styles.cardBase, ...style },
|
|
79
|
+
...props,
|
|
80
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: import_styles.mutedText, children: "No usage data available." })
|
|
81
|
+
}
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
const meterName = label ?? data.meterName;
|
|
85
|
+
const useBudget = budget !== void 0 && budget > 0;
|
|
86
|
+
const showBar = useBudget || data.creditedUnits > 0;
|
|
87
|
+
const cap = showBar ? useBudget ? budget : data.creditedUnits : 0;
|
|
88
|
+
const pct = cap > 0 ? Math.min(data.consumedUnits / cap * 100, 100) : 0;
|
|
89
|
+
const color = (0, import_utils.barColor)(pct);
|
|
90
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { ref, className: cls, style: { ...import_styles.cardBase, ...style }, ...props, children: [
|
|
91
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: import_styles.heading, children: meterName }),
|
|
92
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
93
|
+
"div",
|
|
94
|
+
{
|
|
95
|
+
style: {
|
|
96
|
+
display: "flex",
|
|
97
|
+
alignItems: "baseline",
|
|
98
|
+
gap: 6,
|
|
99
|
+
margin: "0 0 14px"
|
|
100
|
+
},
|
|
101
|
+
children: [
|
|
102
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: import_styles.bigNumber, children: (0, import_utils.fmt)(data.consumedUnits, "$") }),
|
|
103
|
+
showBar && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { style: import_styles.subLabel, children: [
|
|
104
|
+
"/ ",
|
|
105
|
+
(0, import_utils.fmt)(cap, "$")
|
|
106
|
+
] })
|
|
107
|
+
]
|
|
108
|
+
}
|
|
109
|
+
),
|
|
110
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: import_styles.barTrack, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
111
|
+
"div",
|
|
112
|
+
{
|
|
113
|
+
style: {
|
|
114
|
+
height: "100%",
|
|
115
|
+
width: `${pct}%`,
|
|
116
|
+
borderRadius: 3,
|
|
117
|
+
background: showBar ? color : "#e5e7eb",
|
|
118
|
+
transition: "width 0.3s ease"
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
) }),
|
|
122
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: import_styles.barLabels, children: [
|
|
123
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: showBar ? `${pct.toFixed(0)}% ${useBudget ? "used" : "consumed"}` : "0 credits" }),
|
|
124
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: showBar ? `${(0, import_utils.fmt)(Math.max(0, cap - data.consumedUnits), "$")} remaining` : `${(0, import_utils.fmt)(data.consumedUnits, "$")} consumed` })
|
|
125
|
+
] })
|
|
126
|
+
] });
|
|
127
|
+
});
|
|
128
|
+
CreditUsagePolar.displayName = "CreditUsagePolar";
|
|
129
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
130
|
+
0 && (module.exports = {
|
|
131
|
+
CreditUsagePolar
|
|
132
|
+
});
|
|
133
|
+
//# sourceMappingURL=CreditUsagePolar.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/polar/CreditUsagePolar.tsx"],"sourcesContent":["'use client';\n\nimport React, { useState, useEffect } from 'react';\nimport {\n cardBase,\n heading,\n mutedText,\n bigNumber,\n subLabel,\n barTrack,\n barLabels,\n} from '../styles.js';\nimport { barColor, fmt } from '../utils.js';\nimport { fetchPolarUsage } from './fetchPolarUsage.js';\nimport type { PolarUsageData } from './types.js';\n\nexport interface CreditUsagePolarProps extends React.HTMLAttributes<HTMLDivElement> {\n userId: string;\n budget?: number;\n label?: string;\n}\n\nexport const CreditUsagePolar = React.forwardRef<\n HTMLDivElement,\n CreditUsagePolarProps\n>(({ userId, budget, label, className, style, ...props }, ref) => {\n const cls = (className ?? '').trim();\n const [data, setData] = useState<PolarUsageData | null>(null);\n const [loading, setLoading] = useState(true);\n\n useEffect(() => {\n let cancelled = false;\n setLoading(true);\n (async () => {\n try {\n const result = await fetchPolarUsage(userId);\n if (!cancelled) setData(result);\n } catch {\n if (!cancelled) setData(null);\n } finally {\n if (!cancelled) setLoading(false);\n }\n })();\n return () => {\n cancelled = true;\n };\n }, [userId]);\n\n if (loading) {\n return (\n <div\n ref={ref}\n className={cls}\n style={{ ...cardBase, height: 120, opacity: 0.5, ...style }}\n {...props}\n />\n );\n }\n\n if (!data?.found) {\n return (\n <div\n ref={ref}\n className={cls}\n style={{ ...cardBase, ...style }}\n {...props}\n >\n <p style={mutedText}>No usage data available.</p>\n </div>\n );\n }\n\n const meterName = label ?? data.meterName;\n const useBudget = budget !== undefined && budget > 0;\n const showBar = useBudget || data.creditedUnits > 0;\n const cap = showBar ? (useBudget ? budget! : data.creditedUnits) : 0;\n const pct = cap > 0 ? Math.min((data.consumedUnits / cap) * 100, 100) : 0;\n const color = barColor(pct);\n\n return (\n <div ref={ref} className={cls} style={{ ...cardBase, ...style }} {...props}>\n <p style={heading}>{meterName}</p>\n <div\n style={{\n display: 'flex',\n alignItems: 'baseline',\n gap: 6,\n margin: '0 0 14px',\n }}\n >\n <span style={bigNumber}>{fmt(data.consumedUnits, '$')}</span>\n {showBar && <span style={subLabel}>/ {fmt(cap, '$')}</span>}\n </div>\n <div style={barTrack}>\n <div\n style={{\n height: '100%',\n width: `${pct}%`,\n borderRadius: 3,\n background: showBar ? color : '#e5e7eb',\n transition: 'width 0.3s ease',\n }}\n />\n </div>\n <div style={barLabels}>\n <span>\n {showBar\n ? `${pct.toFixed(0)}% ${useBudget ? 'used' : 'consumed'}`\n : '0 credits'}\n </span>\n <span>\n {showBar\n ? `${fmt(Math.max(0, cap - data.consumedUnits), '$')} remaining`\n : `${fmt(data.consumedUnits, '$')} consumed`}\n </span>\n </div>\n </div>\n );\n});\nCreditUsagePolar.displayName = 'CreditUsagePolar';\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAkDM;AAhDN,mBAA2C;AAC3C,oBAQO;AACP,mBAA8B;AAC9B,6BAAgC;AASzB,MAAM,mBAAmB,aAAAA,QAAM,WAGpC,CAAC,EAAE,QAAQ,QAAQ,OAAO,WAAW,OAAO,GAAG,MAAM,GAAG,QAAQ;AAChE,QAAM,OAAO,aAAa,IAAI,KAAK;AACnC,QAAM,CAAC,MAAM,OAAO,QAAI,uBAAgC,IAAI;AAC5D,QAAM,CAAC,SAAS,UAAU,QAAI,uBAAS,IAAI;AAE3C,8BAAU,MAAM;AACd,QAAI,YAAY;AAChB,eAAW,IAAI;AACf,KAAC,YAAY;AACX,UAAI;AACF,cAAM,SAAS,UAAM,wCAAgB,MAAM;AAC3C,YAAI,CAAC,UAAW,SAAQ,MAAM;AAAA,MAChC,QAAQ;AACN,YAAI,CAAC,UAAW,SAAQ,IAAI;AAAA,MAC9B,UAAE;AACA,YAAI,CAAC,UAAW,YAAW,KAAK;AAAA,MAClC;AAAA,IACF,GAAG;AACH,WAAO,MAAM;AACX,kBAAY;AAAA,IACd;AAAA,EACF,GAAG,CAAC,MAAM,CAAC;AAEX,MAAI,SAAS;AACX,WACE;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA,WAAW;AAAA,QACX,OAAO,EAAE,GAAG,wBAAU,QAAQ,KAAK,SAAS,KAAK,GAAG,MAAM;AAAA,QACzD,GAAG;AAAA;AAAA,IACN;AAAA,EAEJ;AAEA,MAAI,CAAC,MAAM,OAAO;AAChB,WACE;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA,WAAW;AAAA,QACX,OAAO,EAAE,GAAG,wBAAU,GAAG,MAAM;AAAA,QAC9B,GAAG;AAAA,QAEJ,sDAAC,OAAE,OAAO,yBAAW,sCAAwB;AAAA;AAAA,IAC/C;AAAA,EAEJ;AAEA,QAAM,YAAY,SAAS,KAAK;AAChC,QAAM,YAAY,WAAW,UAAa,SAAS;AACnD,QAAM,UAAU,aAAa,KAAK,gBAAgB;AAClD,QAAM,MAAM,UAAW,YAAY,SAAU,KAAK,gBAAiB;AACnE,QAAM,MAAM,MAAM,IAAI,KAAK,IAAK,KAAK,gBAAgB,MAAO,KAAK,GAAG,IAAI;AACxE,QAAM,YAAQ,uBAAS,GAAG;AAE1B,SACE,6CAAC,SAAI,KAAU,WAAW,KAAK,OAAO,EAAE,GAAG,wBAAU,GAAG,MAAM,GAAI,GAAG,OACnE;AAAA,gDAAC,OAAE,OAAO,uBAAU,qBAAU;AAAA,IAC9B;AAAA,MAAC;AAAA;AAAA,QACC,OAAO;AAAA,UACL,SAAS;AAAA,UACT,YAAY;AAAA,UACZ,KAAK;AAAA,UACL,QAAQ;AAAA,QACV;AAAA,QAEA;AAAA,sDAAC,UAAK,OAAO,yBAAY,gCAAI,KAAK,eAAe,GAAG,GAAE;AAAA,UACrD,WAAW,6CAAC,UAAK,OAAO,wBAAU;AAAA;AAAA,gBAAG,kBAAI,KAAK,GAAG;AAAA,aAAE;AAAA;AAAA;AAAA,IACtD;AAAA,IACA,4CAAC,SAAI,OAAO,wBACV;AAAA,MAAC;AAAA;AAAA,QACC,OAAO;AAAA,UACL,QAAQ;AAAA,UACR,OAAO,GAAG,GAAG;AAAA,UACb,cAAc;AAAA,UACd,YAAY,UAAU,QAAQ;AAAA,UAC9B,YAAY;AAAA,QACd;AAAA;AAAA,IACF,GACF;AAAA,IACA,6CAAC,SAAI,OAAO,yBACV;AAAA,kDAAC,UACE,oBACG,GAAG,IAAI,QAAQ,CAAC,CAAC,KAAK,YAAY,SAAS,UAAU,KACrD,aACN;AAAA,MACA,4CAAC,UACE,oBACG,OAAG,kBAAI,KAAK,IAAI,GAAG,MAAM,KAAK,aAAa,GAAG,GAAG,CAAC,eAClD,OAAG,kBAAI,KAAK,eAAe,GAAG,CAAC,aACrC;AAAA,OACF;AAAA,KACF;AAEJ,CAAC;AACD,iBAAiB,cAAc;","names":["React"]}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
interface CreditUsagePolarProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
4
|
+
userId: string;
|
|
5
|
+
budget?: number;
|
|
6
|
+
label?: string;
|
|
7
|
+
}
|
|
8
|
+
declare const CreditUsagePolar: React.ForwardRefExoticComponent<CreditUsagePolarProps & React.RefAttributes<HTMLDivElement>>;
|
|
9
|
+
|
|
10
|
+
export { CreditUsagePolar, type CreditUsagePolarProps };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
interface CreditUsagePolarProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
4
|
+
userId: string;
|
|
5
|
+
budget?: number;
|
|
6
|
+
label?: string;
|
|
7
|
+
}
|
|
8
|
+
declare const CreditUsagePolar: React.ForwardRefExoticComponent<CreditUsagePolarProps & React.RefAttributes<HTMLDivElement>>;
|
|
9
|
+
|
|
10
|
+
export { CreditUsagePolar, type CreditUsagePolarProps };
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import React, { useState, useEffect } from "react";
|
|
4
|
+
import {
|
|
5
|
+
cardBase,
|
|
6
|
+
heading,
|
|
7
|
+
mutedText,
|
|
8
|
+
bigNumber,
|
|
9
|
+
subLabel,
|
|
10
|
+
barTrack,
|
|
11
|
+
barLabels
|
|
12
|
+
} from "../styles.js";
|
|
13
|
+
import { barColor, fmt } from "../utils.js";
|
|
14
|
+
import { fetchPolarUsage } from "./fetchPolarUsage.js";
|
|
15
|
+
const CreditUsagePolar = React.forwardRef(({ userId, budget, label, className, style, ...props }, ref) => {
|
|
16
|
+
const cls = (className ?? "").trim();
|
|
17
|
+
const [data, setData] = useState(null);
|
|
18
|
+
const [loading, setLoading] = useState(true);
|
|
19
|
+
useEffect(() => {
|
|
20
|
+
let cancelled = false;
|
|
21
|
+
setLoading(true);
|
|
22
|
+
(async () => {
|
|
23
|
+
try {
|
|
24
|
+
const result = await fetchPolarUsage(userId);
|
|
25
|
+
if (!cancelled) setData(result);
|
|
26
|
+
} catch {
|
|
27
|
+
if (!cancelled) setData(null);
|
|
28
|
+
} finally {
|
|
29
|
+
if (!cancelled) setLoading(false);
|
|
30
|
+
}
|
|
31
|
+
})();
|
|
32
|
+
return () => {
|
|
33
|
+
cancelled = true;
|
|
34
|
+
};
|
|
35
|
+
}, [userId]);
|
|
36
|
+
if (loading) {
|
|
37
|
+
return /* @__PURE__ */ jsx(
|
|
38
|
+
"div",
|
|
39
|
+
{
|
|
40
|
+
ref,
|
|
41
|
+
className: cls,
|
|
42
|
+
style: { ...cardBase, height: 120, opacity: 0.5, ...style },
|
|
43
|
+
...props
|
|
44
|
+
}
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
if (!data?.found) {
|
|
48
|
+
return /* @__PURE__ */ jsx(
|
|
49
|
+
"div",
|
|
50
|
+
{
|
|
51
|
+
ref,
|
|
52
|
+
className: cls,
|
|
53
|
+
style: { ...cardBase, ...style },
|
|
54
|
+
...props,
|
|
55
|
+
children: /* @__PURE__ */ jsx("p", { style: mutedText, children: "No usage data available." })
|
|
56
|
+
}
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
const meterName = label ?? data.meterName;
|
|
60
|
+
const useBudget = budget !== void 0 && budget > 0;
|
|
61
|
+
const showBar = useBudget || data.creditedUnits > 0;
|
|
62
|
+
const cap = showBar ? useBudget ? budget : data.creditedUnits : 0;
|
|
63
|
+
const pct = cap > 0 ? Math.min(data.consumedUnits / cap * 100, 100) : 0;
|
|
64
|
+
const color = barColor(pct);
|
|
65
|
+
return /* @__PURE__ */ jsxs("div", { ref, className: cls, style: { ...cardBase, ...style }, ...props, children: [
|
|
66
|
+
/* @__PURE__ */ jsx("p", { style: heading, children: meterName }),
|
|
67
|
+
/* @__PURE__ */ jsxs(
|
|
68
|
+
"div",
|
|
69
|
+
{
|
|
70
|
+
style: {
|
|
71
|
+
display: "flex",
|
|
72
|
+
alignItems: "baseline",
|
|
73
|
+
gap: 6,
|
|
74
|
+
margin: "0 0 14px"
|
|
75
|
+
},
|
|
76
|
+
children: [
|
|
77
|
+
/* @__PURE__ */ jsx("span", { style: bigNumber, children: fmt(data.consumedUnits, "$") }),
|
|
78
|
+
showBar && /* @__PURE__ */ jsxs("span", { style: subLabel, children: [
|
|
79
|
+
"/ ",
|
|
80
|
+
fmt(cap, "$")
|
|
81
|
+
] })
|
|
82
|
+
]
|
|
83
|
+
}
|
|
84
|
+
),
|
|
85
|
+
/* @__PURE__ */ jsx("div", { style: barTrack, children: /* @__PURE__ */ jsx(
|
|
86
|
+
"div",
|
|
87
|
+
{
|
|
88
|
+
style: {
|
|
89
|
+
height: "100%",
|
|
90
|
+
width: `${pct}%`,
|
|
91
|
+
borderRadius: 3,
|
|
92
|
+
background: showBar ? color : "#e5e7eb",
|
|
93
|
+
transition: "width 0.3s ease"
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
) }),
|
|
97
|
+
/* @__PURE__ */ jsxs("div", { style: barLabels, children: [
|
|
98
|
+
/* @__PURE__ */ jsx("span", { children: showBar ? `${pct.toFixed(0)}% ${useBudget ? "used" : "consumed"}` : "0 credits" }),
|
|
99
|
+
/* @__PURE__ */ jsx("span", { children: showBar ? `${fmt(Math.max(0, cap - data.consumedUnits), "$")} remaining` : `${fmt(data.consumedUnits, "$")} consumed` })
|
|
100
|
+
] })
|
|
101
|
+
] });
|
|
102
|
+
});
|
|
103
|
+
CreditUsagePolar.displayName = "CreditUsagePolar";
|
|
104
|
+
export {
|
|
105
|
+
CreditUsagePolar
|
|
106
|
+
};
|
|
107
|
+
//# sourceMappingURL=CreditUsagePolar.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/polar/CreditUsagePolar.tsx"],"sourcesContent":["'use client';\n\nimport React, { useState, useEffect } from 'react';\nimport {\n cardBase,\n heading,\n mutedText,\n bigNumber,\n subLabel,\n barTrack,\n barLabels,\n} from '../styles.js';\nimport { barColor, fmt } from '../utils.js';\nimport { fetchPolarUsage } from './fetchPolarUsage.js';\nimport type { PolarUsageData } from './types.js';\n\nexport interface CreditUsagePolarProps extends React.HTMLAttributes<HTMLDivElement> {\n userId: string;\n budget?: number;\n label?: string;\n}\n\nexport const CreditUsagePolar = React.forwardRef<\n HTMLDivElement,\n CreditUsagePolarProps\n>(({ userId, budget, label, className, style, ...props }, ref) => {\n const cls = (className ?? '').trim();\n const [data, setData] = useState<PolarUsageData | null>(null);\n const [loading, setLoading] = useState(true);\n\n useEffect(() => {\n let cancelled = false;\n setLoading(true);\n (async () => {\n try {\n const result = await fetchPolarUsage(userId);\n if (!cancelled) setData(result);\n } catch {\n if (!cancelled) setData(null);\n } finally {\n if (!cancelled) setLoading(false);\n }\n })();\n return () => {\n cancelled = true;\n };\n }, [userId]);\n\n if (loading) {\n return (\n <div\n ref={ref}\n className={cls}\n style={{ ...cardBase, height: 120, opacity: 0.5, ...style }}\n {...props}\n />\n );\n }\n\n if (!data?.found) {\n return (\n <div\n ref={ref}\n className={cls}\n style={{ ...cardBase, ...style }}\n {...props}\n >\n <p style={mutedText}>No usage data available.</p>\n </div>\n );\n }\n\n const meterName = label ?? data.meterName;\n const useBudget = budget !== undefined && budget > 0;\n const showBar = useBudget || data.creditedUnits > 0;\n const cap = showBar ? (useBudget ? budget! : data.creditedUnits) : 0;\n const pct = cap > 0 ? Math.min((data.consumedUnits / cap) * 100, 100) : 0;\n const color = barColor(pct);\n\n return (\n <div ref={ref} className={cls} style={{ ...cardBase, ...style }} {...props}>\n <p style={heading}>{meterName}</p>\n <div\n style={{\n display: 'flex',\n alignItems: 'baseline',\n gap: 6,\n margin: '0 0 14px',\n }}\n >\n <span style={bigNumber}>{fmt(data.consumedUnits, '$')}</span>\n {showBar && <span style={subLabel}>/ {fmt(cap, '$')}</span>}\n </div>\n <div style={barTrack}>\n <div\n style={{\n height: '100%',\n width: `${pct}%`,\n borderRadius: 3,\n background: showBar ? color : '#e5e7eb',\n transition: 'width 0.3s ease',\n }}\n />\n </div>\n <div style={barLabels}>\n <span>\n {showBar\n ? `${pct.toFixed(0)}% ${useBudget ? 'used' : 'consumed'}`\n : '0 credits'}\n </span>\n <span>\n {showBar\n ? `${fmt(Math.max(0, cap - data.consumedUnits), '$')} remaining`\n : `${fmt(data.consumedUnits, '$')} consumed`}\n </span>\n </div>\n </div>\n );\n});\nCreditUsagePolar.displayName = 'CreditUsagePolar';\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
"use server";
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
+
};
|
|
11
|
+
var __copyProps = (to, from, except, desc) => {
|
|
12
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
+
for (let key of __getOwnPropNames(from))
|
|
14
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
20
|
+
var createCheckout_exports = {};
|
|
21
|
+
__export(createCheckout_exports, {
|
|
22
|
+
createCheckout: () => createCheckout
|
|
23
|
+
});
|
|
24
|
+
module.exports = __toCommonJS(createCheckout_exports);
|
|
25
|
+
var import_sdk = require("@polar-sh/sdk");
|
|
26
|
+
async function createCheckout(productId, userId, origin) {
|
|
27
|
+
const polar = new import_sdk.Polar({
|
|
28
|
+
accessToken: process.env.POLAR_ACCESS_TOKEN,
|
|
29
|
+
server: process.env.POLAR_SERVER ?? "sandbox"
|
|
30
|
+
});
|
|
31
|
+
try {
|
|
32
|
+
const checkout = await polar.checkouts.create({
|
|
33
|
+
products: [productId],
|
|
34
|
+
externalCustomerId: userId,
|
|
35
|
+
successUrl: `${origin}/usage`
|
|
36
|
+
});
|
|
37
|
+
return checkout.url;
|
|
38
|
+
} catch (error) {
|
|
39
|
+
console.error("Create checkout failed:", error);
|
|
40
|
+
throw new Error("Failed to create checkout", { cause: error });
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
44
|
+
0 && (module.exports = {
|
|
45
|
+
createCheckout
|
|
46
|
+
});
|
|
47
|
+
//# sourceMappingURL=createCheckout.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/polar/createCheckout.ts"],"sourcesContent":["'use server';\n\nimport { Polar } from '@polar-sh/sdk';\n\n/**\n * Creates a Polar checkout session and returns the URL.\n * @param productId - the Polar product ID\n * @param userId - the external customer ID\n * @param origin - the application origin for the success URL\n */\nexport async function createCheckout(\n productId: string,\n userId: string,\n origin: string,\n) {\n const polar = new Polar({\n accessToken: process.env.POLAR_ACCESS_TOKEN,\n server: (process.env.POLAR_SERVER as 'sandbox' | 'production') ?? 'sandbox',\n });\n\n try {\n const checkout = await polar.checkouts.create({\n products: [productId],\n externalCustomerId: userId,\n successUrl: `${origin}/usage`,\n });\n return checkout.url;\n } catch (error) {\n console.error('Create checkout failed:', error);\n throw new Error('Failed to create checkout', { cause: error });\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAEA,iBAAsB;AAQtB,eAAsB,eACpB,WACA,QACA,QACA;AACA,QAAM,QAAQ,IAAI,iBAAM;AAAA,IACtB,aAAa,QAAQ,IAAI;AAAA,IACzB,QAAS,QAAQ,IAAI,gBAA6C;AAAA,EACpE,CAAC;AAED,MAAI;AACF,UAAM,WAAW,MAAM,MAAM,UAAU,OAAO;AAAA,MAC5C,UAAU,CAAC,SAAS;AAAA,MACpB,oBAAoB;AAAA,MACpB,YAAY,GAAG,MAAM;AAAA,IACvB,CAAC;AACD,WAAO,SAAS;AAAA,EAClB,SAAS,OAAO;AACd,YAAQ,MAAM,2BAA2B,KAAK;AAC9C,UAAM,IAAI,MAAM,6BAA6B,EAAE,OAAO,MAAM,CAAC;AAAA,EAC/D;AACF;","names":[]}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Creates a Polar checkout session and returns the URL.
|
|
3
|
+
* @param productId - the Polar product ID
|
|
4
|
+
* @param userId - the external customer ID
|
|
5
|
+
* @param origin - the application origin for the success URL
|
|
6
|
+
*/
|
|
7
|
+
declare function createCheckout(productId: string, userId: string, origin: string): Promise<string>;
|
|
8
|
+
|
|
9
|
+
export { createCheckout };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Creates a Polar checkout session and returns the URL.
|
|
3
|
+
* @param productId - the Polar product ID
|
|
4
|
+
* @param userId - the external customer ID
|
|
5
|
+
* @param origin - the application origin for the success URL
|
|
6
|
+
*/
|
|
7
|
+
declare function createCheckout(productId: string, userId: string, origin: string): Promise<string>;
|
|
8
|
+
|
|
9
|
+
export { createCheckout };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use server";
|
|
2
|
+
import { Polar } from "@polar-sh/sdk";
|
|
3
|
+
async function createCheckout(productId, userId, origin) {
|
|
4
|
+
const polar = new Polar({
|
|
5
|
+
accessToken: process.env.POLAR_ACCESS_TOKEN,
|
|
6
|
+
server: process.env.POLAR_SERVER ?? "sandbox"
|
|
7
|
+
});
|
|
8
|
+
try {
|
|
9
|
+
const checkout = await polar.checkouts.create({
|
|
10
|
+
products: [productId],
|
|
11
|
+
externalCustomerId: userId,
|
|
12
|
+
successUrl: `${origin}/usage`
|
|
13
|
+
});
|
|
14
|
+
return checkout.url;
|
|
15
|
+
} catch (error) {
|
|
16
|
+
console.error("Create checkout failed:", error);
|
|
17
|
+
throw new Error("Failed to create checkout", { cause: error });
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
export {
|
|
21
|
+
createCheckout
|
|
22
|
+
};
|
|
23
|
+
//# sourceMappingURL=createCheckout.js.map
|