@crediball/react 0.14.0 → 0.16.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/dist/CrediballProvider.d.ts +5 -2
- package/dist/CrediballProvider.js +4 -1
- package/dist/PaywallModal.d.ts +13 -4
- package/dist/PaywallModal.js +71 -30
- package/package.json +2 -2
|
@@ -87,8 +87,11 @@ export interface CrediballProviderProps {
|
|
|
87
87
|
/** Override the custom-amount maximum (defaults to the dashboard's configured maximum). */
|
|
88
88
|
customMax?: number;
|
|
89
89
|
/**
|
|
90
|
-
* Show a "Have a promo code?" field in the paywall
|
|
91
|
-
*
|
|
90
|
+
* Show a "Have a promo code?" field in the paywall. Auto-derived from your
|
|
91
|
+
* dashboard's Growth → Promotions config: shown automatically once you have
|
|
92
|
+
* an active Checkout promotion, same as `allowCustom`/custom top-up. Pass
|
|
93
|
+
* this only to override (e.g. `false` to force-hide it, or `true` to show it
|
|
94
|
+
* before you've set one up). The code is passed through to
|
|
92
95
|
* `onSelectPackage`/`onTopup`, or included automatically in the built-in
|
|
93
96
|
* checkout when neither is provided.
|
|
94
97
|
*/
|
|
@@ -261,12 +261,15 @@ export function CrediballProvider({ children, publishableKey, userId, apiUrl, po
|
|
|
261
261
|
const effectiveAllowCustom = allowCustom ?? customCfg?.enabled ?? false;
|
|
262
262
|
const effectiveCustomMin = customMin ?? customCfg?.minEur;
|
|
263
263
|
const effectiveCustomMax = customMax ?? customCfg?.maxEur ?? undefined;
|
|
264
|
+
// Same auto-derivation for the promo-code field: a developer who set up a
|
|
265
|
+
// Checkout promotion in Growth gets the field for free, no code change.
|
|
266
|
+
const effectiveAllowPromoCode = allowPromoCode ?? pkgs?.hasActiveCheckoutPromotion ?? false;
|
|
264
267
|
// Published theme → --crediball-* CSS vars, applied on a display:contents
|
|
265
268
|
// wrapper so it themes every descendant (and the paywall) without adding a
|
|
266
269
|
// layout box. Host props/CSS are overridden by design (dashboard wins).
|
|
267
270
|
const themeVars = applyRemoteTheme ? themeToCssVars(uiTheme) : {};
|
|
268
271
|
const hasThemeVars = Object.keys(themeVars).length > 0;
|
|
269
|
-
const inner = (_jsxs(_Fragment, { children: [children, _jsx(PaywallModal, { open: open, packages: pkgs?.packages, onSelectPackage: handleSelectPackage, subscriptionPlans: pkgs?.subscriptionPlans, onSelectPlan: handleSelectPlan, activeSubscription: pkgs?.activeSubscription, onCancelSubscription: onCancelSubscription ? handleCancelSubscription : undefined, autoTopup: pkgs?.autoTopup, onEnableAutoTopup: handleEnableAutoTopup, amounts: amounts, amountPrefix: `Add ${currencySymbol}`, onAdd: handleAdd, onClose: hidePaywall, allowCustom: effectiveAllowCustom, customMin: effectiveCustomMin, customMax: effectiveCustomMax, allowPromoCode:
|
|
272
|
+
const inner = (_jsxs(_Fragment, { children: [children, _jsx(PaywallModal, { open: open, packages: pkgs?.packages, onSelectPackage: handleSelectPackage, subscriptionPlans: pkgs?.subscriptionPlans, onSelectPlan: handleSelectPlan, activeSubscription: pkgs?.activeSubscription, onCancelSubscription: onCancelSubscription ? handleCancelSubscription : undefined, autoTopup: pkgs?.autoTopup, onEnableAutoTopup: handleEnableAutoTopup, amounts: amounts, amountPrefix: `Add ${currencySymbol}`, onAdd: handleAdd, onClose: hidePaywall, allowCustom: effectiveAllowCustom, customMin: effectiveCustomMin, customMax: effectiveCustomMax, allowPromoCode: effectiveAllowPromoCode, promoCodeLabel: promoCodeLabel, customTopupRate: pkgs?.customTopup.enabled ? pkgs.customTopup.rate : undefined, currencySymbol: currencySymbol, balance: snapshot.balance ?? undefined, balanceRate: pkgs?.customTopup.enabled ? pkgs.customTopup.rate : undefined, currency: pkgs?.currency, usage: snapshot.usage?.usedCredits ?? undefined, title: title ?? uiContent?.paywallTitle, description: description ?? uiContent?.paywallDescription, addButtonText: uiContent?.paywallButtonText, referralLink: referral?.link ?? undefined, referralReward: referral?.rewardCredits, referredReward: referral?.referredRewardCredits, referralLabel: uiContent?.referralLabel, accentColor: accentColor })] }));
|
|
270
273
|
const configCtx = useMemo(() => ({ publishableKey, userId, apiUrl }), [publishableKey, userId, apiUrl]);
|
|
271
274
|
return (_jsx(CrediballContext.Provider, { value: ctx, children: _jsx(CrediballConfigContext.Provider, { value: configCtx, children: hasThemeVars ? (_jsx("div", { style: { display: "contents", ...themeVars }, children: inner })) : (inner) }) }));
|
|
272
275
|
}
|
package/dist/PaywallModal.d.ts
CHANGED
|
@@ -154,9 +154,18 @@ export interface PaywallModalProps extends CrediballThemeOverrides {
|
|
|
154
154
|
/** Credits earned per successful referral, shown in the refer-a-friend blurb. */
|
|
155
155
|
referralReward?: number;
|
|
156
156
|
/**
|
|
157
|
-
*
|
|
158
|
-
*
|
|
159
|
-
*
|
|
157
|
+
* Credits the referred friend earns, shown alongside `referralReward` in the
|
|
158
|
+
* refer-a-friend blurb (0/undefined omits that clause). Wired automatically
|
|
159
|
+
* by <CrediballProvider> when referrals are enabled in the dashboard.
|
|
160
|
+
*/
|
|
161
|
+
referredReward?: number;
|
|
162
|
+
/**
|
|
163
|
+
* Label above the referral link. `{credits}` is replaced with `referralReward`,
|
|
164
|
+
* `{referredCredits}` with `referredReward`. A `\n` renders as a line break.
|
|
165
|
+
* Defaults to a two-line "Refer a friend.\nYou earn {credits} credits and
|
|
166
|
+
* your friend {referredCredits} credits" when `referredReward` is set, or a
|
|
167
|
+
* single-line "Refer a friend · earn {credits} credits" otherwise. Shown as
|
|
168
|
+
* written (not uppercased), so lowercase/sentence case is preserved.
|
|
160
169
|
*/
|
|
161
170
|
referralLabel?: string;
|
|
162
171
|
style?: CSSProperties;
|
|
@@ -166,4 +175,4 @@ export interface PaywallModalProps extends CrediballThemeOverrides {
|
|
|
166
175
|
* continue. The host controls when it appears; shows a small "Powered by
|
|
167
176
|
* Crediball" line by default (set `hideBranding` to remove it).
|
|
168
177
|
*/
|
|
169
|
-
export declare function PaywallModal({ open, packages, onSelectPackage, subscriptionPlans, onSelectPlan, activeSubscription, onCancelSubscription, autoTopup, onEnableAutoTopup, amounts, amountPrefix, title, description, onAdd, onClose, allowCustom, allowPromoCode, promoCodeLabel, addButtonText, customMin, customMax, customTopupRate, currencySymbol, balance, balanceRate, currency, usage, usageLabel, hideBranding, referralLink, referralReward, referralLabel, accentColor, style, }: PaywallModalProps): import("react").JSX.Element | null;
|
|
178
|
+
export declare function PaywallModal({ open, packages, onSelectPackage, subscriptionPlans, onSelectPlan, activeSubscription, onCancelSubscription, autoTopup, onEnableAutoTopup, amounts, amountPrefix, title, description, onAdd, onClose, allowCustom, allowPromoCode, promoCodeLabel, addButtonText, customMin, customMax, customTopupRate, currencySymbol, balance, balanceRate, currency, usage, usageLabel, hideBranding, referralLink, referralReward, referredReward, referralLabel, accentColor, style, }: PaywallModalProps): import("react").JSX.Element | null;
|
package/dist/PaywallModal.js
CHANGED
|
@@ -9,13 +9,12 @@ const PERIOD_SUFFIX = {
|
|
|
9
9
|
monthly: "mo",
|
|
10
10
|
yearly: "yr",
|
|
11
11
|
};
|
|
12
|
-
/** Shared
|
|
12
|
+
/** Shared eyebrow-label style used above the subscribe/buy-credits sections. */
|
|
13
13
|
function sectionLabelStyle(marginBottom) {
|
|
14
14
|
return {
|
|
15
15
|
fontSize: 11,
|
|
16
16
|
fontWeight: 600,
|
|
17
17
|
letterSpacing: "0.06em",
|
|
18
|
-
textTransform: "uppercase",
|
|
19
18
|
color: theme.inkMuted,
|
|
20
19
|
marginBottom,
|
|
21
20
|
};
|
|
@@ -25,7 +24,7 @@ function sectionLabelStyle(marginBottom) {
|
|
|
25
24
|
* continue. The host controls when it appears; shows a small "Powered by
|
|
26
25
|
* Crediball" line by default (set `hideBranding` to remove it).
|
|
27
26
|
*/
|
|
28
|
-
export function PaywallModal({ open, packages, onSelectPackage, subscriptionPlans, onSelectPlan, activeSubscription, onCancelSubscription, autoTopup, onEnableAutoTopup, amounts = [5, 10], amountPrefix = "Add €", title = "You need more credits to continue.", description = "Top up to keep using this feature.", onAdd, onClose, allowCustom = false, allowPromoCode = false, promoCodeLabel = "Have a promo code?", addButtonText = "Add", customMin = 1, customMax, customTopupRate, currencySymbol = "€", balance, balanceRate, currency = "EUR", usage, usageLabel = "Usage", hideBranding = false, referralLink, referralReward, referralLabel
|
|
27
|
+
export function PaywallModal({ open, packages, onSelectPackage, subscriptionPlans, onSelectPlan, activeSubscription, onCancelSubscription, autoTopup, onEnableAutoTopup, amounts = [5, 10], amountPrefix = "Add €", title = "You need more credits to continue.", description = "Top up to keep using this feature.", onAdd, onClose, allowCustom = false, allowPromoCode = false, promoCodeLabel = "Have a promo code?", addButtonText = "Add", customMin = 1, customMax, customTopupRate, currencySymbol = "€", balance, balanceRate, currency = "EUR", usage, usageLabel = "Usage", hideBranding = false, referralLink, referralReward, referredReward, referralLabel, accentColor, style, }) {
|
|
29
28
|
// Stack the top-up buttons one-per-line when the dialog itself is narrow.
|
|
30
29
|
// Measured off the dialog's own box (via ResizeObserver) rather than the
|
|
31
30
|
// window — in normal use the two are the same width, but this also makes
|
|
@@ -43,6 +42,7 @@ export function PaywallModal({ open, packages, onSelectPackage, subscriptionPlan
|
|
|
43
42
|
const [autoTopupThreshold, setAutoTopupThreshold] = useState("");
|
|
44
43
|
const [promoCodeOpen, setPromoCodeOpen] = useState(false);
|
|
45
44
|
const [promoCode, setPromoCode] = useState("");
|
|
45
|
+
const [promoCodeTouched, setPromoCodeTouched] = useState(false);
|
|
46
46
|
useEffect(() => {
|
|
47
47
|
const el = overlayRef.current;
|
|
48
48
|
if (!el || typeof ResizeObserver === "undefined")
|
|
@@ -90,6 +90,10 @@ export function PaywallModal({ open, packages, onSelectPackage, subscriptionPlan
|
|
|
90
90
|
const trimmed = promoCode.trim();
|
|
91
91
|
return trimmed || undefined;
|
|
92
92
|
}
|
|
93
|
+
// Format-only — whether the code is actually active/redeemable is only known
|
|
94
|
+
// server-side when a purchase is made (see enteredCode()'s callers). This
|
|
95
|
+
// just catches an obvious typo/paste mistake before then.
|
|
96
|
+
const promoCodeFormatValid = !promoCode.trim() || /^[A-Z0-9_-]+$/.test(promoCode.trim());
|
|
93
97
|
function submitCustom() {
|
|
94
98
|
const amt = Number(customValue);
|
|
95
99
|
if (!Number.isFinite(amt) || amt <= 0) {
|
|
@@ -127,7 +131,37 @@ export function PaywallModal({ open, packages, onSelectPackage, subscriptionPlan
|
|
|
127
131
|
padding: "8px 16px",
|
|
128
132
|
borderRadius: theme.radiusPill,
|
|
129
133
|
};
|
|
130
|
-
|
|
134
|
+
// Package/plan buttons: name + credits stacked on the left, price on the right.
|
|
135
|
+
const optionButtonStyle = {
|
|
136
|
+
...buttonStyle,
|
|
137
|
+
flex: "none",
|
|
138
|
+
display: "flex",
|
|
139
|
+
justifyContent: "space-between",
|
|
140
|
+
alignItems: "center",
|
|
141
|
+
gap: 16,
|
|
142
|
+
padding: "10px 16px",
|
|
143
|
+
};
|
|
144
|
+
const optionLeftStyle = {
|
|
145
|
+
display: "flex",
|
|
146
|
+
flexDirection: "column",
|
|
147
|
+
alignItems: "flex-start",
|
|
148
|
+
flex: 1,
|
|
149
|
+
minWidth: 0,
|
|
150
|
+
};
|
|
151
|
+
const optionNameStyle = { fontSize: 17, fontWeight: 600, lineHeight: 1.2 };
|
|
152
|
+
const optionCreditsStyle = { fontSize: 13, opacity: 0.85, lineHeight: 1.2 };
|
|
153
|
+
const optionPriceStyle = {
|
|
154
|
+
fontSize: 17,
|
|
155
|
+
fontWeight: 600,
|
|
156
|
+
whiteSpace: "nowrap",
|
|
157
|
+
flexShrink: 0,
|
|
158
|
+
};
|
|
159
|
+
const defaultReferralLabel = referredReward != null && referredReward > 0
|
|
160
|
+
? "Refer a friend.\nYou earn {credits} credits and your friend {referredCredits} credits"
|
|
161
|
+
: "Refer a friend · earn {credits} credits";
|
|
162
|
+
const resolvedReferralLabel = (referralLabel ?? defaultReferralLabel)
|
|
163
|
+
.replace("{credits}", formatCredits(referralReward ?? 0))
|
|
164
|
+
.replace("{referredCredits}", formatCredits(referredReward ?? 0));
|
|
131
165
|
// Same rounding the actual charge uses (see /api/public/topup/checkout),
|
|
132
166
|
// so this preview never promises a different number than what's granted.
|
|
133
167
|
const customAmountParsed = Number(customValue);
|
|
@@ -154,6 +188,18 @@ export function PaywallModal({ open, packages, onSelectPackage, subscriptionPlan
|
|
|
154
188
|
}, onClick: onClose, children: _jsxs("div", { onClick: (e) => e.stopPropagation(), style: {
|
|
155
189
|
width: "100%",
|
|
156
190
|
maxWidth: 420,
|
|
191
|
+
// Cap the card to the overlay's own (already viewport-correct, since
|
|
192
|
+
// it's `position: fixed; inset: 0`) content box, and let it scroll
|
|
193
|
+
// internally past that — otherwise a host enabling many optional
|
|
194
|
+
// sections (balance, subscribe, promo code, packages, custom amount,
|
|
195
|
+
// auto top-up, referral) can produce a card taller than the mobile
|
|
196
|
+
// viewport, which the centered overlay then clips top and bottom
|
|
197
|
+
// with no way to reach the rest.
|
|
198
|
+
maxHeight: "100%",
|
|
199
|
+
overflowY: "auto",
|
|
200
|
+
WebkitOverflowScrolling: "touch",
|
|
201
|
+
overscrollBehavior: "contain",
|
|
202
|
+
boxSizing: "border-box",
|
|
157
203
|
padding: 32,
|
|
158
204
|
borderRadius: theme.radiusCard,
|
|
159
205
|
background: theme.canvas,
|
|
@@ -188,13 +234,22 @@ export function PaywallModal({ open, packages, onSelectPackage, subscriptionPlan
|
|
|
188
234
|
color: theme.inkMuted,
|
|
189
235
|
fontFamily: theme.font,
|
|
190
236
|
textDecoration: "underline",
|
|
191
|
-
}, children: cancelPending ? "Canceling…" : "Cancel subscription" }))] })), !activeSubscription && subscriptionPlans && subscriptionPlans.length > 0 && (_jsxs("div", { style: { marginTop: 24 }, children: [_jsx("div", { style: sectionLabelStyle(8), children: "Subscribe" }), _jsx("div", { style: { display: "flex", flexDirection: "column", gap: 8 }, children: subscriptionPlans.map((plan) => (_jsxs("button", { onClick: () => onSelectPlan?.(plan), style: {
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
237
|
+
}, children: cancelPending ? "Canceling…" : "Cancel subscription" }))] })), !activeSubscription && subscriptionPlans && subscriptionPlans.length > 0 && (_jsxs("div", { style: { marginTop: 24 }, children: [_jsx("div", { style: sectionLabelStyle(8), children: "Subscribe" }), _jsx("div", { style: { display: "flex", flexDirection: "column", gap: 8 }, children: subscriptionPlans.map((plan) => (_jsxs("button", { onClick: () => onSelectPlan?.(plan), style: optionButtonStyle, children: [_jsxs("span", { style: optionLeftStyle, children: [_jsx("span", { style: optionNameStyle, children: plan.name }), _jsxs("span", { style: optionCreditsStyle, children: [formatCredits(plan.credits), " credits"] })] }), _jsxs("span", { style: optionPriceStyle, children: [formatMoney(plan.price, currency), "/", PERIOD_SUFFIX[plan.period]] })] }, plan.id))) })] })), _jsxs("div", { style: { display: "flex", flexDirection: "column", gap: 10, marginTop: 24 }, children: [(!activeSubscription && subscriptionPlans && subscriptionPlans.length > 0) && (_jsx("div", { style: sectionLabelStyle(-2), children: "Or buy credits" })), activeSubscription && packages && packages.length > 0 && (_jsx("div", { style: sectionLabelStyle(-2), children: "Add extra credits" })), packages && packages.length > 0
|
|
238
|
+
? packages.map((pkg) => (_jsxs("button", { onClick: () => onSelectPackage?.(pkg, enteredCode()), style: optionButtonStyle, children: [_jsxs("span", { style: optionLeftStyle, children: [_jsx("span", { style: optionNameStyle, children: pkg.name }), _jsxs("span", { style: optionCreditsStyle, children: [formatCredits(pkg.credits), " credits"] })] }), _jsx("span", { style: optionPriceStyle, children: formatMoney(pkg.price, currency) })] }, pkg.id)))
|
|
239
|
+
: (!activeSubscription && (_jsx("div", { style: { display: "flex", flexDirection: narrow ? "column" : "row", gap: 12 }, children: amounts.map((amount) => (_jsxs("button", { onClick: () => onAdd?.(amount, enteredCode()), 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: 14, color: theme.inkMuted }, children: currencySymbol }), _jsx("input", { value: customValue, onChange: (e) => setCustomValue(e.target.value), inputMode: "decimal", placeholder: String(customMin), style: {
|
|
240
|
+
flex: 1,
|
|
241
|
+
minWidth: 0,
|
|
242
|
+
appearance: "none",
|
|
243
|
+
fontFamily: theme.font,
|
|
244
|
+
fontSize: 14,
|
|
245
|
+
lineHeight: "20px",
|
|
246
|
+
padding: "8px 12px",
|
|
247
|
+
borderRadius: theme.radiusPill,
|
|
248
|
+
border: `1px solid ${theme.hairline}`,
|
|
249
|
+
color: theme.ink,
|
|
250
|
+
background: theme.canvas,
|
|
251
|
+
outline: "none",
|
|
252
|
+
} }), _jsx("button", { onClick: submitCustom, style: { ...buttonStyle, flex: "none" }, children: addButtonText })] }), customCreditsPreview != null ? (_jsxs("p", { style: { margin: "6px 0 0", fontSize: 12, color: theme.inkMuted }, children: ["\u2248 ", formatCredits(customCreditsPreview), " credits"] })) : null, customError ? (_jsx("p", { style: { margin: "8px 0 0", fontSize: 13, color: theme.accent }, children: customError })) : null] })) : null, allowPromoCode && !activeSubscription && (_jsx("div", { style: { marginTop: 16 }, children: promoCodeOpen ? (_jsxs("div", { children: [_jsx("div", { style: { ...sectionLabelStyle(6) }, children: promoCodeLabel }), _jsx("input", { value: promoCode, onChange: (e) => setPromoCode(e.target.value.toUpperCase()), onBlur: () => setPromoCodeTouched(true), placeholder: "PROMOCODE", style: {
|
|
198
253
|
width: "100%",
|
|
199
254
|
boxSizing: "border-box",
|
|
200
255
|
appearance: "none",
|
|
@@ -203,11 +258,11 @@ export function PaywallModal({ open, packages, onSelectPackage, subscriptionPlan
|
|
|
203
258
|
lineHeight: "20px",
|
|
204
259
|
padding: "8px 12px",
|
|
205
260
|
borderRadius: theme.radiusPill,
|
|
206
|
-
border: `1px solid ${theme.hairline}`,
|
|
261
|
+
border: `1px solid ${promoCodeTouched && !promoCodeFormatValid ? theme.accent : theme.hairline}`,
|
|
207
262
|
color: theme.ink,
|
|
208
263
|
background: theme.canvas,
|
|
209
264
|
outline: "none",
|
|
210
|
-
} })] })) : (_jsx("button", { onClick: () => setPromoCodeOpen(true), style: {
|
|
265
|
+
} }), promoCodeTouched && !promoCodeFormatValid ? (_jsx("p", { style: { margin: "6px 0 0", fontSize: 12, color: theme.accent }, children: "Promo codes only contain letters, numbers, - and _." })) : null] })) : (_jsx("button", { onClick: () => setPromoCodeOpen(true), style: {
|
|
211
266
|
appearance: "none",
|
|
212
267
|
border: "none",
|
|
213
268
|
background: "transparent",
|
|
@@ -217,22 +272,7 @@ export function PaywallModal({ open, packages, onSelectPackage, subscriptionPlan
|
|
|
217
272
|
color: theme.inkMuted,
|
|
218
273
|
fontFamily: theme.font,
|
|
219
274
|
textDecoration: "underline",
|
|
220
|
-
}, children: promoCodeLabel })) })),
|
|
221
|
-
? packages.map((pkg) => (_jsxs("button", { onClick: () => onSelectPackage?.(pkg, enteredCode()), 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: [formatMoney(pkg.price, currency), " \u00B7 ", formatCredits(pkg.credits), " cr"] })] }, pkg.id)))
|
|
222
|
-
: (!activeSubscription && (_jsx("div", { style: { display: "flex", flexDirection: narrow ? "column" : "row", gap: 12 }, children: amounts.map((amount) => (_jsxs("button", { onClick: () => onAdd?.(amount, enteredCode()), 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: 14, color: theme.inkMuted }, children: currencySymbol }), _jsx("input", { value: customValue, onChange: (e) => setCustomValue(e.target.value), inputMode: "decimal", placeholder: String(customMin), style: {
|
|
223
|
-
flex: 1,
|
|
224
|
-
minWidth: 0,
|
|
225
|
-
appearance: "none",
|
|
226
|
-
fontFamily: theme.font,
|
|
227
|
-
fontSize: 14,
|
|
228
|
-
lineHeight: "20px",
|
|
229
|
-
padding: "8px 12px",
|
|
230
|
-
borderRadius: theme.radiusPill,
|
|
231
|
-
border: `1px solid ${theme.hairline}`,
|
|
232
|
-
color: theme.ink,
|
|
233
|
-
background: theme.canvas,
|
|
234
|
-
outline: "none",
|
|
235
|
-
} }), _jsx("button", { onClick: submitCustom, style: { ...buttonStyle, flex: "none" }, children: addButtonText })] }), customCreditsPreview != null ? (_jsxs("p", { style: { margin: "6px 0 0", fontSize: 12, color: theme.inkMuted }, children: ["\u2248 ", formatCredits(customCreditsPreview), " credits"] })) : null, customError ? (_jsx("p", { style: { margin: "8px 0 0", fontSize: 13, color: theme.accent }, children: customError })) : null] })) : null, packages && packages.length > 0 && (_jsx("div", { style: { marginTop: 16 }, children: autoTopup?.enabled && autoTopup.status === "active" ? (_jsxs("p", { style: { margin: 0, fontSize: 12, color: theme.inkMuted }, children: ["Auto top-up is on \u2014 buying", " ", packages.find((p) => p.id === autoTopup.packageId)?.name ?? "your package", " whenever your balance drops below ", formatCredits(autoTopup.thresholdCredits), " credits."] })) : autoTopup?.enabled && (autoTopup.status === "needs_auth" || autoTopup.status === "failed") ? (_jsxs("div", { children: [_jsx("p", { style: { margin: 0, fontSize: 12, color: theme.accent }, children: autoTopup.status === "needs_auth"
|
|
275
|
+
}, children: promoCodeLabel })) })), packages && packages.length > 0 && (_jsx("div", { style: { marginTop: 16 }, children: autoTopup?.enabled && autoTopup.status === "active" ? (_jsxs("p", { style: { margin: 0, fontSize: 12, color: theme.inkMuted }, children: ["Auto top-up is on \u2014 buying", " ", packages.find((p) => p.id === autoTopup.packageId)?.name ?? "your package", " whenever your balance drops below ", formatCredits(autoTopup.thresholdCredits), " credits."] })) : autoTopup?.enabled && (autoTopup.status === "needs_auth" || autoTopup.status === "failed") ? (_jsxs("div", { children: [_jsx("p", { style: { margin: 0, fontSize: 12, color: theme.accent }, children: autoTopup.status === "needs_auth"
|
|
236
276
|
? "Auto top-up needs you to re-confirm your payment method."
|
|
237
277
|
: "Auto top-up's last charge failed." }), _jsx("button", { onClick: () => onEnableAutoTopup?.({
|
|
238
278
|
packageId: autoTopup.packageId,
|
|
@@ -298,6 +338,7 @@ export function PaywallModal({ open, packages, onSelectPackage, subscriptionPlan
|
|
|
298
338
|
fontWeight: 600,
|
|
299
339
|
color: theme.inkMuted,
|
|
300
340
|
marginBottom: 8,
|
|
341
|
+
whiteSpace: "pre-line",
|
|
301
342
|
}, children: resolvedReferralLabel }), _jsxs("div", { style: { display: "flex", gap: 8, alignItems: "center" }, children: [_jsx("div", { title: referralLink, style: {
|
|
302
343
|
flex: 1,
|
|
303
344
|
minWidth: 0,
|
|
@@ -322,5 +363,5 @@ export function PaywallModal({ open, packages, onSelectPackage, subscriptionPlan
|
|
|
322
363
|
padding: "8px 16px",
|
|
323
364
|
borderRadius: theme.radiusPill,
|
|
324
365
|
whiteSpace: "nowrap",
|
|
325
|
-
}, children: referralCopied ? "Copied!" : "Copy" })] })] })) : null, !hideBranding && (_jsx("div", { style: { display: "flex", justifyContent: "flex-end", marginTop:
|
|
366
|
+
}, children: referralCopied ? "Copied!" : "Copy" })] })] })) : null, !hideBranding && (_jsx("div", { style: { display: "flex", justifyContent: "flex-end", marginTop: 20 }, children: _jsx("span", { style: { fontSize: 10, color: theme.inkMuted }, children: "Powered by Crediball." }) }))] }) }));
|
|
326
367
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@crediball/react",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.16.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>",
|
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
"react": ">=18"
|
|
52
52
|
},
|
|
53
53
|
"dependencies": {
|
|
54
|
-
"@crediball/core": "^0.
|
|
54
|
+
"@crediball/core": "^0.9.0"
|
|
55
55
|
},
|
|
56
56
|
"devDependencies": {
|
|
57
57
|
"@types/react": "^18.3.11",
|