@bravely-studios/account-web 0.3.10 → 0.4.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/README.md +122 -5
- package/dist/ActivationStateMachine.d.ts +1 -1
- package/dist/ActivationStateMachine.d.ts.map +1 -1
- package/dist/ActivationStateMachine.js +6 -2
- package/dist/ActivationStateMachine.js.map +1 -1
- package/dist/BravelyAccountManager.d.ts +108 -2
- package/dist/BravelyAccountManager.d.ts.map +1 -1
- package/dist/BravelyAccountManager.js +376 -29
- package/dist/BravelyAccountManager.js.map +1 -1
- package/dist/components/BravelyProviderButtons.d.ts.map +1 -1
- package/dist/components/BravelyProviderButtons.js.map +1 -1
- package/dist/components/BravelySignInScreen.d.ts +55 -0
- package/dist/components/BravelySignInScreen.d.ts.map +1 -0
- package/dist/components/BravelySignInScreen.js +141 -0
- package/dist/components/BravelySignInScreen.js.map +1 -0
- package/dist/components/OfferSlotGrid.d.ts +204 -0
- package/dist/components/OfferSlotGrid.d.ts.map +1 -0
- package/dist/components/OfferSlotGrid.js +490 -0
- package/dist/components/OfferSlotGrid.js.map +1 -0
- package/dist/index.d.ts +5 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -1
- package/dist/index.js.map +1 -1
- package/dist/installMetrics.d.ts +40 -0
- package/dist/installMetrics.d.ts.map +1 -0
- package/dist/installMetrics.js +128 -0
- package/dist/installMetrics.js.map +1 -0
- package/dist/storage.d.ts +23 -10
- package/dist/storage.d.ts.map +1 -1
- package/dist/storage.js +52 -16
- package/dist/storage.js.map +1 -1
- package/dist/types.d.ts +8 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +2 -1
- package/dist/types.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BravelyProviderButtons.d.ts","sourceRoot":"","sources":["../../src/components/BravelyProviderButtons.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"BravelyProviderButtons.d.ts","sourceRoot":"","sources":["../../src/components/BravelyProviderButtons.tsx"],"names":[],"mappings":"AAsCA,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAEzD,sCAAsC;AACtC,MAAM,MAAM,YAAY,GAAG,OAAO,GAAG,QAAQ,GAAG,OAAO,CAAC;AAExD;;;;;;;GAOG;AACH,MAAM,MAAM,0BAA0B,GAClC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACpC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAExC,MAAM,WAAW,2BAA2B;IAC1C,4BAA4B;IAC5B,KAAK,EAAE,0BAA0B,CAAC;IAClC,yEAAyE;IACzE,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,yDAAyD;IACzD,KAAK,EAAE,CAAC,QAAQ,EAAE,YAAY,KAAK,IAAI,CAAC;IACxC,0DAA0D;IAC1D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,4DAA4D;IAC5D,cAAc,CAAC,EAAE,aAAa,CAAC;CAChC;AAyJD;;;GAGG;AACH,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,2BAA2B,GACjC,YAAY,CAkGd"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BravelyProviderButtons.js","sourceRoot":"","sources":["../../src/components/BravelyProviderButtons.tsx"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"BravelyProviderButtons.js","sourceRoot":"","sources":["../../src/components/BravelyProviderButtons.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { type CSSProperties, type ReactElement, type ReactNode } from "react";
|
|
2
|
+
import { type BravelyProviderButtonStyle, type ProviderHint } from "./BravelyProviderButtons.js";
|
|
3
|
+
/** Locked copy for the offline (can't-reach) recoverable state. */
|
|
4
|
+
export declare const SIGN_IN_OFFLINE_HEADLINE = "Can't reach Bravely";
|
|
5
|
+
export declare const SIGN_IN_OFFLINE_BODY = "Check your connection and try again.";
|
|
6
|
+
export declare const SIGN_IN_OFFLINE_RETRY_LABEL = "Retry";
|
|
7
|
+
export interface BravelySignInScreenProps {
|
|
8
|
+
/** App display name (e.g. "Todoing.ly"). Rendered under the icon. */
|
|
9
|
+
appName: string;
|
|
10
|
+
/** App icon image URL (square; rendered at 72×72 with rounded corners). */
|
|
11
|
+
appIconSrc?: string;
|
|
12
|
+
/** Custom icon node — wins over `appIconSrc` when both are provided. */
|
|
13
|
+
icon?: ReactNode;
|
|
14
|
+
/** The ONE value-prop line. Exactly one sentence; no marketing stack. */
|
|
15
|
+
valueProp: string;
|
|
16
|
+
/** Theme + per-app accent (same contract as `BravelyProviderButtons`). */
|
|
17
|
+
style: BravelyProviderButtonStyle;
|
|
18
|
+
/** True while an auth attempt is in flight; disables and dims the picker. */
|
|
19
|
+
isBusy?: boolean;
|
|
20
|
+
/**
|
|
21
|
+
* Provider pick handler. Forward the hint to
|
|
22
|
+
* `manager.signIn({ provider })` so the hosted shell's provider-hint fast
|
|
23
|
+
* lane skips the duplicate picker.
|
|
24
|
+
*/
|
|
25
|
+
onContinue: (provider: ProviderHint) => void;
|
|
26
|
+
/**
|
|
27
|
+
* Offline/can't-reach state (recoverable, screen one). When true the
|
|
28
|
+
* picker is replaced by the locked "Can't reach Bravely" copy + Retry.
|
|
29
|
+
*/
|
|
30
|
+
offline?: boolean;
|
|
31
|
+
/** Retry handler for the offline state. */
|
|
32
|
+
onRetry?: () => void;
|
|
33
|
+
/**
|
|
34
|
+
* Fired exactly once per mount when the screen is presented. The host
|
|
35
|
+
* emits `login_screen_shown` (exact name) here with the `install_id`.
|
|
36
|
+
* Fires in the offline state too — an offline first screen is still a
|
|
37
|
+
* presented login screen (it closes first-screen drop-out blindness).
|
|
38
|
+
*/
|
|
39
|
+
onShown?: () => void;
|
|
40
|
+
/** Privacy Policy footer link. Defaults to the Bravely hub page. */
|
|
41
|
+
privacyHref?: string;
|
|
42
|
+
/** Terms of Service footer link. Defaults to the Bravely hub page. */
|
|
43
|
+
termsHref?: string;
|
|
44
|
+
/** Optional class name applied to the outer container. */
|
|
45
|
+
className?: string;
|
|
46
|
+
/** Optional inline style applied to the outer container. */
|
|
47
|
+
containerStyle?: CSSProperties;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Render the canonical login-first screen. Centered single column, capped at
|
|
51
|
+
* 360px wide (the picker's hosted-shell width), vertically centered in its
|
|
52
|
+
* container — give it a full-viewport parent.
|
|
53
|
+
*/
|
|
54
|
+
export declare function BravelySignInScreen(props: BravelySignInScreenProps): ReactElement;
|
|
55
|
+
//# sourceMappingURL=BravelySignInScreen.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BravelySignInScreen.d.ts","sourceRoot":"","sources":["../../src/components/BravelySignInScreen.tsx"],"names":[],"mappings":"AAgDA,OAAO,EAAqB,KAAK,aAAa,EAAE,KAAK,YAAY,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AACjG,OAAO,EAEL,KAAK,0BAA0B,EAC/B,KAAK,YAAY,EAClB,MAAM,6BAA6B,CAAC;AAKrC,mEAAmE;AACnE,eAAO,MAAM,wBAAwB,wBAAwB,CAAC;AAC9D,eAAO,MAAM,oBAAoB,yCAAyC,CAAC;AAC3E,eAAO,MAAM,2BAA2B,UAAU,CAAC;AAEnD,MAAM,WAAW,wBAAwB;IACvC,qEAAqE;IACrE,OAAO,EAAE,MAAM,CAAC;IAChB,2EAA2E;IAC3E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,wEAAwE;IACxE,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,yEAAyE;IACzE,SAAS,EAAE,MAAM,CAAC;IAClB,0EAA0E;IAC1E,KAAK,EAAE,0BAA0B,CAAC;IAClC,6EAA6E;IAC7E,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB;;;;OAIG;IACH,UAAU,EAAE,CAAC,QAAQ,EAAE,YAAY,KAAK,IAAI,CAAC;IAC7C;;;OAGG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,2CAA2C;IAC3C,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB;;;;;OAKG;IACH,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,oEAAoE;IACpE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,sEAAsE;IACtE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,0DAA0D;IAC1D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,4DAA4D;IAC5D,cAAc,CAAC,EAAE,aAAa,CAAC;CAChC;AAKD;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,wBAAwB,GAAG,YAAY,CA8JjF"}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
// `<BravelySignInScreen>` — the canonical login-first first screen for the
|
|
3
|
+
// Bravely web family (login-first cutover D1, spec `onboarding.login_first`).
|
|
4
|
+
//
|
|
5
|
+
// The FIRST screen on first launch, everywhere: app icon + name, ONE
|
|
6
|
+
// value-prop line, the locked `BravelyProviderButtons` picker
|
|
7
|
+
// [Sign in with Apple, Sign in with Google, Continue with email], and
|
|
8
|
+
// passive Privacy/Terms footer links. The screen IS both sign-in and
|
|
9
|
+
// sign-up — the server creates-or-matches the account (ADR 0014 hosted
|
|
10
|
+
// shell untouched).
|
|
11
|
+
//
|
|
12
|
+
// Hard rules (enforced by construction — do NOT add these as props):
|
|
13
|
+
// - NO skip, NO guest lane, NO free lane.
|
|
14
|
+
// - NO "already have an account" fork (no fork exists; one screen).
|
|
15
|
+
// - NO pre-auth welcome/survey/cross-sell content.
|
|
16
|
+
//
|
|
17
|
+
// Offline first launch (D1): pass `offline` to render the recoverable
|
|
18
|
+
// "Can't reach Bravely" state with a Retry button on screen one. Signed-in
|
|
19
|
+
// RELAUNCHES never hard-block offline — that's the manager's job (72h
|
|
20
|
+
// entitlement cache + tokens never wiped on transport failure); this screen
|
|
21
|
+
// only ever shows to signed-out users.
|
|
22
|
+
//
|
|
23
|
+
// Metrics (D6, spec `analytics.install_path`): `onShown` fires exactly once
|
|
24
|
+
// per mount — the host MUST emit `login_screen_shown` (exact name) there,
|
|
25
|
+
// carrying the `install_id` from `getOrMintInstallId()`. Do not strip it.
|
|
26
|
+
//
|
|
27
|
+
// Usage:
|
|
28
|
+
//
|
|
29
|
+
// ```tsx
|
|
30
|
+
// import {
|
|
31
|
+
// BravelySignInScreen,
|
|
32
|
+
// getOrMintInstallId,
|
|
33
|
+
// } from "@bravely-studios/account-web";
|
|
34
|
+
//
|
|
35
|
+
// <BravelySignInScreen
|
|
36
|
+
// appName="Todoing.ly"
|
|
37
|
+
// appIconSrc="/icon-256.png"
|
|
38
|
+
// valueProp="Every task, every device, always in sync."
|
|
39
|
+
// style={{ variant: "dark", accent: "#3B6EF0" }}
|
|
40
|
+
// isBusy={isAuthorizing}
|
|
41
|
+
// onContinue={(provider) => manager.signIn({ provider })}
|
|
42
|
+
// onShown={async () => {
|
|
43
|
+
// posthog.capture("login_screen_shown", {
|
|
44
|
+
// install_id: await getOrMintInstallId(),
|
|
45
|
+
// });
|
|
46
|
+
// }}
|
|
47
|
+
// />
|
|
48
|
+
// ```
|
|
49
|
+
import { useEffect, useRef } from "react";
|
|
50
|
+
import { BravelyProviderButtons, } from "./BravelyProviderButtons.js";
|
|
51
|
+
const SYSTEM_FONT = '-apple-system, BlinkMacSystemFont, "Segoe UI Variable", "Segoe UI", Roboto, "Inter", "Helvetica Neue", Arial, sans-serif';
|
|
52
|
+
/** Locked copy for the offline (can't-reach) recoverable state. */
|
|
53
|
+
export const SIGN_IN_OFFLINE_HEADLINE = "Can't reach Bravely";
|
|
54
|
+
export const SIGN_IN_OFFLINE_BODY = "Check your connection and try again.";
|
|
55
|
+
export const SIGN_IN_OFFLINE_RETRY_LABEL = "Retry";
|
|
56
|
+
const DEFAULT_PRIVACY_HREF = "https://bravely.dev/privacy";
|
|
57
|
+
const DEFAULT_TERMS_HREF = "https://bravely.dev/terms";
|
|
58
|
+
/**
|
|
59
|
+
* Render the canonical login-first screen. Centered single column, capped at
|
|
60
|
+
* 360px wide (the picker's hosted-shell width), vertically centered in its
|
|
61
|
+
* container — give it a full-viewport parent.
|
|
62
|
+
*/
|
|
63
|
+
export function BravelySignInScreen(props) {
|
|
64
|
+
const { appName, appIconSrc, icon, valueProp, style, isBusy = false, onContinue, offline = false, onRetry, onShown, privacyHref = DEFAULT_PRIVACY_HREF, termsHref = DEFAULT_TERMS_HREF, className, containerStyle, } = props;
|
|
65
|
+
const isLight = style.variant === "light";
|
|
66
|
+
const fg = isLight ? "#1f1a16" : "#f5f3ff";
|
|
67
|
+
const muted = isLight ? "rgba(31, 26, 22, 0.62)" : "rgba(245, 243, 255, 0.6)";
|
|
68
|
+
// `login_screen_shown` seam — once per mount, guarded against StrictMode
|
|
69
|
+
// double-invocation of effects.
|
|
70
|
+
const shownRef = useRef(false);
|
|
71
|
+
useEffect(() => {
|
|
72
|
+
if (shownRef.current)
|
|
73
|
+
return;
|
|
74
|
+
shownRef.current = true;
|
|
75
|
+
onShown?.();
|
|
76
|
+
// Mount-only by design; `onShown` identity changes must not re-fire.
|
|
77
|
+
}, []);
|
|
78
|
+
const container = {
|
|
79
|
+
boxSizing: "border-box",
|
|
80
|
+
display: "flex",
|
|
81
|
+
flexDirection: "column",
|
|
82
|
+
alignItems: "center",
|
|
83
|
+
justifyContent: "center",
|
|
84
|
+
gap: 0,
|
|
85
|
+
width: "100%",
|
|
86
|
+
minHeight: "100%",
|
|
87
|
+
padding: "48px 24px",
|
|
88
|
+
fontFamily: SYSTEM_FONT,
|
|
89
|
+
color: fg,
|
|
90
|
+
textAlign: "center",
|
|
91
|
+
...containerStyle,
|
|
92
|
+
};
|
|
93
|
+
const linkStyle = {
|
|
94
|
+
color: muted,
|
|
95
|
+
textDecoration: "underline",
|
|
96
|
+
textUnderlineOffset: 3,
|
|
97
|
+
fontSize: 12.5,
|
|
98
|
+
fontWeight: 500,
|
|
99
|
+
};
|
|
100
|
+
return (_jsxs("div", { className: className, style: container, "data-bravely-component": "sign-in-screen", "data-variant": style.variant, children: [icon ??
|
|
101
|
+
(appIconSrc ? (_jsx("img", { src: appIconSrc, alt: `${appName} icon`, width: 72, height: 72, style: { width: 72, height: 72, borderRadius: 16, display: "block" } })) : null), _jsx("h1", { style: {
|
|
102
|
+
margin: "16px 0 0",
|
|
103
|
+
fontSize: 26,
|
|
104
|
+
fontWeight: 800,
|
|
105
|
+
letterSpacing: "-0.02em",
|
|
106
|
+
lineHeight: 1.2,
|
|
107
|
+
}, children: appName }), _jsx("p", { "data-bravely-sign-in": "value-prop", style: {
|
|
108
|
+
margin: "10px 0 0",
|
|
109
|
+
maxWidth: 360,
|
|
110
|
+
fontSize: 15,
|
|
111
|
+
fontWeight: 400,
|
|
112
|
+
lineHeight: 1.45,
|
|
113
|
+
color: muted,
|
|
114
|
+
}, children: valueProp }), _jsx("div", { style: { width: "100%", maxWidth: 360, marginTop: 28 }, children: offline ? (_jsxs("div", { "data-bravely-sign-in": "offline", style: { display: "flex", flexDirection: "column", gap: 10 }, children: [_jsx("div", { style: { fontSize: 16, fontWeight: 700, color: fg }, children: SIGN_IN_OFFLINE_HEADLINE }), _jsx("div", { style: { fontSize: 13.5, color: muted }, children: SIGN_IN_OFFLINE_BODY }), _jsx("button", { type: "button", onClick: () => onRetry?.(), "aria-label": SIGN_IN_OFFLINE_RETRY_LABEL, "data-bravely-sign-in": "retry", style: {
|
|
115
|
+
boxSizing: "border-box",
|
|
116
|
+
width: "100%",
|
|
117
|
+
minHeight: 48,
|
|
118
|
+
marginTop: 6,
|
|
119
|
+
padding: "0 14px",
|
|
120
|
+
display: "inline-flex",
|
|
121
|
+
alignItems: "center",
|
|
122
|
+
justifyContent: "center",
|
|
123
|
+
borderRadius: 12,
|
|
124
|
+
border: "1px solid transparent",
|
|
125
|
+
background: style.accent,
|
|
126
|
+
color: isLight ? "#ffffff" : "#0b0716",
|
|
127
|
+
fontFamily: SYSTEM_FONT,
|
|
128
|
+
fontSize: 14,
|
|
129
|
+
fontWeight: 600,
|
|
130
|
+
cursor: "pointer",
|
|
131
|
+
appearance: "none",
|
|
132
|
+
WebkitAppearance: "none",
|
|
133
|
+
}, children: SIGN_IN_OFFLINE_RETRY_LABEL })] })) : (_jsx(BravelyProviderButtons, { style: style, isBusy: isBusy, onTap: onContinue })) }), _jsxs("footer", { "data-bravely-sign-in": "legal", style: {
|
|
134
|
+
marginTop: 24,
|
|
135
|
+
display: "flex",
|
|
136
|
+
gap: 16,
|
|
137
|
+
alignItems: "center",
|
|
138
|
+
justifyContent: "center",
|
|
139
|
+
}, children: [_jsx("a", { href: privacyHref, target: "_blank", rel: "noreferrer", style: linkStyle, children: "Privacy Policy" }), _jsx("a", { href: termsHref, target: "_blank", rel: "noreferrer", style: linkStyle, children: "Terms of Service" })] })] }));
|
|
140
|
+
}
|
|
141
|
+
//# sourceMappingURL=BravelySignInScreen.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BravelySignInScreen.js","sourceRoot":"","sources":["../../src/components/BravelySignInScreen.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
import { type CSSProperties, type ReactElement, type ReactNode } from "react";
|
|
2
|
+
import type { CheckoutPlan } from "../types.js";
|
|
3
|
+
/**
|
|
4
|
+
* The three offer slots. Maps 1:1 to the `slot` parameter the
|
|
5
|
+
* `/api/payfirst/checkout-sessions` endpoint accepts.
|
|
6
|
+
*/
|
|
7
|
+
export type OfferSlotKind = "HOOK" | "GSO" | "FRONT_LTV";
|
|
8
|
+
/**
|
|
9
|
+
* App "value application" type. RVA HOOK = recurring $0/7d → $9.99/mo trial;
|
|
10
|
+
* IVA HOOK = $19.99 one-time, no trial.
|
|
11
|
+
*/
|
|
12
|
+
export type OfferAppType = "RVA" | "IVA";
|
|
13
|
+
/** CTA visual variant: ghost (HOOK), loud (GSO hero), solid (FRONT_LTV). */
|
|
14
|
+
export type OfferCtaVariant = "ghost" | "loud" | "solid";
|
|
15
|
+
/** One styled text segment; `em` tints it accent or cyan (bold). */
|
|
16
|
+
export interface OfferRichSeg {
|
|
17
|
+
text: string;
|
|
18
|
+
em?: "accent" | "cyan";
|
|
19
|
+
}
|
|
20
|
+
export type OfferRich = OfferRichSeg[];
|
|
21
|
+
/** One bonus-bundle example app row. */
|
|
22
|
+
export interface OfferBonusApp {
|
|
23
|
+
name: string;
|
|
24
|
+
note: string;
|
|
25
|
+
slug: string;
|
|
26
|
+
/**
|
|
27
|
+
* Optional icon URL (host-served). When absent the grid renders an
|
|
28
|
+
* accent-tinted letter monogram — the package bundles no image assets.
|
|
29
|
+
*/
|
|
30
|
+
iconSrc?: string;
|
|
31
|
+
}
|
|
32
|
+
/** The rich bonus block on the GSO / FRONT_LTV cards. */
|
|
33
|
+
export interface OfferBonus {
|
|
34
|
+
label: string;
|
|
35
|
+
headline: OfferRich;
|
|
36
|
+
apps: OfferBonusApp[];
|
|
37
|
+
more: string;
|
|
38
|
+
value: string;
|
|
39
|
+
footer: string;
|
|
40
|
+
}
|
|
41
|
+
/** One rendered slot card's locked copy. */
|
|
42
|
+
export interface OfferSlotCopy {
|
|
43
|
+
kind: OfferSlotKind;
|
|
44
|
+
badge?: string;
|
|
45
|
+
/** Bare plan name ("Monthly" / "Bravely Premium" — never "Name — desc"). */
|
|
46
|
+
name: string;
|
|
47
|
+
/** Muted plan-word descriptor beside the name ("Annual" / "Lifetime"). */
|
|
48
|
+
nameSub?: string;
|
|
49
|
+
/** Muted tagline under the name (locked value-stack line on bundle slots). */
|
|
50
|
+
tagline?: string;
|
|
51
|
+
priceBig: string;
|
|
52
|
+
priceUnit?: string;
|
|
53
|
+
priceSub?: OfferRich;
|
|
54
|
+
bullets: string[];
|
|
55
|
+
/** Guarantee badge line; absent on the RVA HOOK by design. */
|
|
56
|
+
guarantee?: string;
|
|
57
|
+
bonus?: OfferBonus;
|
|
58
|
+
nudge?: OfferRich;
|
|
59
|
+
cta: OfferCtaVariant;
|
|
60
|
+
ctaLabel: string;
|
|
61
|
+
highlighted?: boolean;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* The per-app accent system, mirroring the Swift `OfferTheme` / web
|
|
65
|
+
* `LandingTheme`: `accent` paints eyebrow/em/ghost-border/solid-CTA;
|
|
66
|
+
* `accentStrong` paints the GSO border + CTA gradient end + pills; `cyan`
|
|
67
|
+
* (the app's SECONDARY color) paints the GSO price + bullet checks +
|
|
68
|
+
* Best-Value badge + bonus border + value pill + loud-CTA start.
|
|
69
|
+
*/
|
|
70
|
+
export interface OfferTheme {
|
|
71
|
+
accent: string;
|
|
72
|
+
accentStrong: string;
|
|
73
|
+
cyan: string;
|
|
74
|
+
}
|
|
75
|
+
/** The 30-day guarantee label. */
|
|
76
|
+
export declare const OFFER_GUARANTEE_LINE = "30-Day Money-Back Guarantee";
|
|
77
|
+
/** Hover/disclosure tooltip for the guarantee badge. */
|
|
78
|
+
export declare const OFFER_GUARANTEE_TOOLTIP = "I-Hate-Your-Apps-Give-Me-My-Money-Back: 30 days, no questions.";
|
|
79
|
+
/** Footer note under the whole grid. */
|
|
80
|
+
export declare const OFFER_FOOTER_NOTE = "Bravely Studios \u00B7 one account, every device.";
|
|
81
|
+
/** Footer line inside both bonus blocks. */
|
|
82
|
+
export declare const OFFER_BONUS_FOOTER = "One sign-in \u00B7 instant unlock \u00B7 sync everywhere";
|
|
83
|
+
/**
|
|
84
|
+
* The LOCKED value-stack-dominant tagline (2026-06-01) rendered under the
|
|
85
|
+
* plan name on BOTH bundle slots. Verbatim from `bravely-offer-structure.md`.
|
|
86
|
+
*/
|
|
87
|
+
export declare const OFFER_BUNDLE_TAGLINE = "all 9 apps, every platform, every device, + the bonus bundle";
|
|
88
|
+
/** Per-app offer themes for the 9 production utilities. */
|
|
89
|
+
export declare const OFFER_THEMES: Record<string, OfferTheme>;
|
|
90
|
+
/**
|
|
91
|
+
* Resolve a theme from the canonical app slug. Falls back to Scry's
|
|
92
|
+
* purple/cyan if the slug is unknown (mirrors the Swift lib).
|
|
93
|
+
*/
|
|
94
|
+
export declare function offerThemeForSlug(slug: string): OfferTheme;
|
|
95
|
+
/**
|
|
96
|
+
* The catalog plan token `openCheckout()` should send for a slot. Slot-1
|
|
97
|
+
* tokens are interval-true per the 2026-06-10 catalog rename: `monthly` for
|
|
98
|
+
* RVA apps, `onetime` for IVA apps (the server also aliases legacy tokens,
|
|
99
|
+
* but new clients send the canonical key). GSO/FRONT_LTV resolve server-side
|
|
100
|
+
* to the universal bundle plans.
|
|
101
|
+
*/
|
|
102
|
+
export declare function planTokenForSlot(slot: OfferSlotKind, type: OfferAppType): CheckoutPlan;
|
|
103
|
+
/** Telemetry value per the count-funnel spec (`offer_slot` property). */
|
|
104
|
+
export declare function telemetryValueForSlot(slot: OfferSlotKind): "hook" | "gso" | "ltv";
|
|
105
|
+
/**
|
|
106
|
+
* The canonical bonus-bundle example apps, in order: Scry → PrintScreen.ly →
|
|
107
|
+
* ASAPDF, "+ 5 more". Collision rule: if `<app>` IS one of those 3, drop it
|
|
108
|
+
* and append Diskaroo so the customer always sees 3 *other* apps.
|
|
109
|
+
*/
|
|
110
|
+
export declare function bonusAppsForSlug(slug: string): OfferBonusApp[];
|
|
111
|
+
export interface BuildOfferSlotsArgs {
|
|
112
|
+
/** Display name (e.g. "Scry", "PrintScreen.ly"). */
|
|
113
|
+
appName: string;
|
|
114
|
+
/** Canonical slug — drives the bonus-app collision rule + per-app bullets. */
|
|
115
|
+
appSlug: string;
|
|
116
|
+
/** `RVA` (trial monthly HOOK) or `IVA` (one-time HOOK). */
|
|
117
|
+
type: OfferAppType;
|
|
118
|
+
/** Extra HOOK bullets (between "Full Pro access" and "Cancel anytime"). */
|
|
119
|
+
extraHookBullets?: string[];
|
|
120
|
+
/**
|
|
121
|
+
* Per-bonus-app icon URL resolver (host-served assets). Absent ⇒ letter
|
|
122
|
+
* monograms.
|
|
123
|
+
*/
|
|
124
|
+
bonusIconSrc?: (slug: string) => string | undefined;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Build the canonical 3-slot offer copy — the verbatim strings from the
|
|
128
|
+
* locked offer structure, so every app's purchase surface reads identically
|
|
129
|
+
* (only `<App>` swaps). Render a subset by filtering the result (provisioned
|
|
130
|
+
* slots only).
|
|
131
|
+
*/
|
|
132
|
+
export declare function buildOfferSlots(args: BuildOfferSlotsArgs): OfferSlotCopy[];
|
|
133
|
+
/** Below this viewport width the cards stack single-column + scroll. */
|
|
134
|
+
export declare const OFFER_FIT_MIN_WIDTH = 901;
|
|
135
|
+
/** Scale clamp floor — below this the scale floors and the page scrolls. */
|
|
136
|
+
export declare const OFFER_FIT_MIN_SCALE = 0.5;
|
|
137
|
+
/** Scale clamp ceiling — scale-up allowed to fill large displays. */
|
|
138
|
+
export declare const OFFER_FIT_MAX_SCALE = 3;
|
|
139
|
+
/** Breathing room around the fitted content (px). */
|
|
140
|
+
export declare const OFFER_FIT_PAD = 24;
|
|
141
|
+
/** The grid's natural design width (px) used as the scale-fit basis. */
|
|
142
|
+
export declare const OFFER_NATURAL_WIDTH = 1200;
|
|
143
|
+
export interface OfferFitInput {
|
|
144
|
+
viewportWidth: number;
|
|
145
|
+
viewportHeight: number;
|
|
146
|
+
naturalWidth: number;
|
|
147
|
+
naturalHeight: number;
|
|
148
|
+
pad?: number;
|
|
149
|
+
}
|
|
150
|
+
export type OfferFitResult = {
|
|
151
|
+
mode: "stacked";
|
|
152
|
+
} | {
|
|
153
|
+
mode: "fit";
|
|
154
|
+
/** Uniform scale, clamped to [0.5, 3.0]. */
|
|
155
|
+
scale: number;
|
|
156
|
+
/** True when the raw fit was below the 0.5 floor ⇒ page scrolls. */
|
|
157
|
+
scrollFallback: boolean;
|
|
158
|
+
};
|
|
159
|
+
/**
|
|
160
|
+
* The canonical fit formula (plan §4, verbatim): uniform scale-to-fit BOTH
|
|
161
|
+
* axes, `scale = min(availW/naturalW, availH/naturalH)` clamped to
|
|
162
|
+
* [0.5, 3.0]; below 0.5 the scale floors and the surface falls back to
|
|
163
|
+
* scrolling — never clipping. Pure so tests can pin the math.
|
|
164
|
+
*/
|
|
165
|
+
export declare function computeOfferFit(input: OfferFitInput): OfferFitResult;
|
|
166
|
+
export interface OfferSlotGridProps {
|
|
167
|
+
/**
|
|
168
|
+
* The slot cards to render — EXACTLY these, in order (provisioned slots
|
|
169
|
+
* only). Build with `buildOfferSlots()` and filter as needed.
|
|
170
|
+
*/
|
|
171
|
+
slots: OfferSlotCopy[];
|
|
172
|
+
/** Per-app theme (`offerThemeForSlug(appSlug)`). */
|
|
173
|
+
theme: OfferTheme;
|
|
174
|
+
/** CTA click — the `slot_selected` / checkout entry point. */
|
|
175
|
+
onSelect: (slot: OfferSlotKind) => void;
|
|
176
|
+
/** Fired once per rendered slot per mount — the `slot_viewed` hook. */
|
|
177
|
+
onSlotViewed?: (slot: OfferSlotKind) => void;
|
|
178
|
+
/** Optional content rendered inside the fitted region, above the grid. */
|
|
179
|
+
header?: ReactNode;
|
|
180
|
+
/**
|
|
181
|
+
* Footer note under the grid. Defaults to the locked
|
|
182
|
+
* `OFFER_FOOTER_NOTE`; pass `null` to omit.
|
|
183
|
+
*/
|
|
184
|
+
footerNote?: string | null;
|
|
185
|
+
/** Guarantee badge tooltip. Defaults to the locked copy. */
|
|
186
|
+
guaranteeTooltip?: string;
|
|
187
|
+
/**
|
|
188
|
+
* Scale the content to the viewport (default true). Disable only for
|
|
189
|
+
* embedded/preview contexts; the offer PAGE must keep it on.
|
|
190
|
+
*/
|
|
191
|
+
fitToViewport?: boolean;
|
|
192
|
+
/** Natural design width for the fit basis. Default 1200. */
|
|
193
|
+
naturalWidth?: number;
|
|
194
|
+
/** True while a checkout session is being minted; disables the CTAs. */
|
|
195
|
+
isBusy?: boolean;
|
|
196
|
+
className?: string;
|
|
197
|
+
containerStyle?: CSSProperties;
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Render the canonical 3-up offer grid with full-viewport scale-to-fit.
|
|
201
|
+
* Mount it on a near-full-viewport surface; it owns its own scaling.
|
|
202
|
+
*/
|
|
203
|
+
export declare function OfferSlotGrid(props: OfferSlotGridProps): ReactElement;
|
|
204
|
+
//# sourceMappingURL=OfferSlotGrid.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"OfferSlotGrid.d.ts","sourceRoot":"","sources":["../../src/components/OfferSlotGrid.tsx"],"names":[],"mappings":"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"}
|