@crediball/react 0.1.0 → 0.2.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.
@@ -1,13 +1,36 @@
1
1
  import { type CSSProperties } from "react";
2
2
  import { type CrediballThemeOverrides } from "./theme";
3
+ /** A purchasable credit bundle from the Crediball dashboard (returned by listPackages()). */
4
+ export interface PackageOption {
5
+ id: string;
6
+ name: string;
7
+ price: number;
8
+ credits: number;
9
+ }
3
10
  export interface PaywallModalProps extends CrediballThemeOverrides {
4
11
  open: boolean;
5
- /** Top-up amounts to offer (host decides the meaning, e.g. euros). */
12
+ /**
13
+ * Preferred: pass the packages from `meter.listPackages()` so Crediball can
14
+ * resolve credits and record revenue automatically when the user checks out.
15
+ * The modal renders one button per package (e.g. "Starter — €5 / 10 cr").
16
+ */
17
+ packages?: PackageOption[];
18
+ /**
19
+ * Called when the user selects a package. Use this with `packages` — call
20
+ * `meter.topup({ userId, packageId: pkg.id })` in your backend. No `amount`
21
+ * calculation needed; Crediball derives it from the package.
22
+ */
23
+ onSelectPackage?: (pkg: PackageOption) => void;
24
+ /**
25
+ * Legacy: flat list of euro amounts. Prefer `packages` + `onSelectPackage`.
26
+ * When both are provided, `packages` takes precedence.
27
+ */
6
28
  amounts?: number[];
7
- /** Prefix shown on each button before the amount (default "Add €"). */
29
+ /** Prefix shown on each legacy amount button (default "Add €"). */
8
30
  amountPrefix?: string;
9
31
  title?: string;
10
32
  description?: string;
33
+ /** Called when the user clicks a legacy amount button. */
11
34
  onAdd?: (amount: number) => void;
12
35
  onClose?: () => void;
13
36
  /** When true, show a free-form amount field in addition to the preset buttons. */
@@ -29,4 +52,4 @@ export interface PaywallModalProps extends CrediballThemeOverrides {
29
52
  currency?: string;
30
53
  style?: CSSProperties;
31
54
  }
32
- export declare function PaywallModal({ open, amounts, amountPrefix, title, description, onAdd, onClose, allowCustom, customMin, customMax, currencySymbol, balance, balanceRate, currency, accentColor, style, }: PaywallModalProps): import("react").JSX.Element | null;
55
+ export declare function PaywallModal({ open, packages, onSelectPackage, amounts, amountPrefix, title, description, onAdd, onClose, allowCustom, customMin, customMax, currencySymbol, balance, balanceRate, currency, accentColor, style, }: PaywallModalProps): import("react").JSX.Element | null;
@@ -17,7 +17,7 @@ function fmtMoney(n, currency) {
17
17
  return `${n.toFixed(2)} ${currency}`;
18
18
  }
19
19
  }
20
- export function PaywallModal({ open, amounts = [5, 10], amountPrefix = "Add €", title = "You need more credits to continue.", description = "Top up to keep using this feature.", onAdd, onClose, allowCustom = false, customMin = 1, customMax, currencySymbol = "€", balance, balanceRate, currency = "EUR", accentColor = tokens.primary, style, }) {
20
+ export function PaywallModal({ open, packages, onSelectPackage, amounts = [5, 10], amountPrefix = "Add €", title = "You need more credits to continue.", description = "Top up to keep using this feature.", onAdd, onClose, allowCustom = false, customMin = 1, customMax, currencySymbol = "€", balance, balanceRate, currency = "EUR", accentColor = tokens.primary, style, }) {
21
21
  // Stack the top-up buttons one-per-line on narrow (mobile) screens.
22
22
  const [narrow, setNarrow] = useState(false);
23
23
  const [customValue, setCustomValue] = useState("");
@@ -92,10 +92,12 @@ export function PaywallModal({ open, amounts = [5, 10], amountPrefix = "Add €"
92
92
  marginBottom: 4,
93
93
  }, children: "Your balance" }), _jsxs("div", { style: { display: "flex", alignItems: "baseline", gap: 8, flexWrap: "wrap" }, children: [_jsxs("span", { style: { fontSize: 22, fontWeight: 600, color: tokens.ink }, children: [fmtCredits(balance), " credits"] }), balanceRate && balanceRate > 0 ? (_jsxs("span", { style: { fontSize: 13, color: tokens.inkMuted }, children: ["\u2248 ", fmtMoney(balance / balanceRate, currency)] })) : null] })] })), _jsx("h3", { style: { margin: 0, fontSize: 24, fontWeight: 600, color: tokens.ink, letterSpacing: "-0.01em" }, children: title }), _jsx("p", { style: { marginTop: 8, marginBottom: 0, fontSize: 14, color: tokens.inkMuted }, children: description }), _jsx("div", { style: {
94
94
  display: "flex",
95
- flexDirection: narrow ? "column" : "row",
96
- gap: 12,
95
+ flexDirection: "column",
96
+ gap: 10,
97
97
  marginTop: 24,
98
- }, children: amounts.map((amount) => (_jsxs("button", { onClick: () => onAdd?.(amount), style: buttonStyle, children: [amountPrefix, amount] }, amount))) }), allowCustom ? (_jsxs("div", { style: { marginTop: 12 }, children: [_jsxs("div", { style: { display: "flex", gap: 8, alignItems: "center" }, children: [_jsx("span", { style: { fontSize: 17, color: tokens.inkMuted }, children: currencySymbol }), _jsx("input", { value: customValue, onChange: (e) => setCustomValue(e.target.value), inputMode: "decimal", placeholder: String(customMin), style: {
98
+ }, children: packages && packages.length > 0
99
+ ? packages.map((pkg) => (_jsxs("button", { onClick: () => onSelectPackage?.(pkg), style: { ...buttonStyle, flex: "none", display: "flex", justifyContent: "space-between", alignItems: "center" }, children: [_jsx("span", { children: pkg.name }), _jsxs("span", { style: { opacity: 0.85, fontSize: 14 }, children: [fmtMoney(pkg.price, currency), " \u00B7 ", fmtCredits(pkg.credits), " cr"] })] }, pkg.id)))
100
+ : (_jsx("div", { style: { display: "flex", flexDirection: narrow ? "column" : "row", gap: 12 }, children: amounts.map((amount) => (_jsxs("button", { onClick: () => onAdd?.(amount), style: buttonStyle, children: [amountPrefix, amount] }, amount))) })) }), allowCustom ? (_jsxs("div", { style: { marginTop: 12 }, children: [_jsxs("div", { style: { display: "flex", gap: 8, alignItems: "center" }, children: [_jsx("span", { style: { fontSize: 17, color: tokens.inkMuted }, children: currencySymbol }), _jsx("input", { value: customValue, onChange: (e) => setCustomValue(e.target.value), inputMode: "decimal", placeholder: String(customMin), style: {
99
101
  flex: 1,
100
102
  minWidth: 0,
101
103
  appearance: "none",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@crediball/react",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Drop-in React components for showing Crediball credits inside your AI app.",
5
5
  "license": "MIT",
6
6
  "author": "Filippo Rezzadore <filipporezzadore@gmail.com>",