@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
|
@@ -0,0 +1,490 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
// `<OfferSlotGrid>` — the canonical 3-slot purchase component for the Bravely
|
|
3
|
+
// web family (login-first cutover D3, spec `commerce.offer_page_fit`).
|
|
4
|
+
//
|
|
5
|
+
// The web sibling of Swift `OfferSlotGrid` (bravely-account-swift) and C#
|
|
6
|
+
// `BravelyOfferGrid` (Bravely.Account): three equal-width offer cards side by
|
|
7
|
+
// side (HOOK → GSO/Annual → FRONT_LTV/Lifetime) with the center GSO card
|
|
8
|
+
// visually dominant, cloning the `get.bravely.dev` purchase surface.
|
|
9
|
+
//
|
|
10
|
+
// Source-of-truth specs (clone targets — do NOT drift):
|
|
11
|
+
// - offer model (LOCKED 2026-05-31, names LOCKED 2026-06-01):
|
|
12
|
+
// `00 - AI Instructions/bravely-offer-structure.md`
|
|
13
|
+
// - web reference: `bravely-get/src/landing/{config.ts,LandingTemplate.tsx}`
|
|
14
|
+
// + the offer CSS in `bravely-get/src/app/globals.css`
|
|
15
|
+
//
|
|
16
|
+
// Geometry (spec `commerce.offer_page_fit`, option 3 — web viewport fit):
|
|
17
|
+
// - Full-viewport scale-to-fit BOTH axes, INCLUDING scale-up:
|
|
18
|
+
// `scale = min(availW/naturalW, availH/naturalH)` clamped to [0.5, 3.0].
|
|
19
|
+
// - Below 0.5× the scale floors at 0.5 and the page scrolls — NEVER clip.
|
|
20
|
+
// - NO max-width column cap (the old `max-w-[84rem]` cap is gone; on large
|
|
21
|
+
// displays the grid scales up past it edge-to-edge).
|
|
22
|
+
// - Below the 3-up breakpoint (901px) cards stack single-column and scroll
|
|
23
|
+
// naturally (three tall cards can't sensibly fit one phone screen).
|
|
24
|
+
//
|
|
25
|
+
// Slots: the grid renders EXACTLY the `slots` it is given — provisioned
|
|
26
|
+
// slots only (J5). `buildOfferSlots()` produces the locked 3-slot copy;
|
|
27
|
+
// hosts filter it if a slot is unprovisioned for their surface.
|
|
28
|
+
//
|
|
29
|
+
// Analytics hooks (spec `analytics.install_path`): `onSlotViewed` fires once
|
|
30
|
+
// per rendered slot per mount (`slot_viewed`); `onSelect` is the
|
|
31
|
+
// `slot_selected` + checkout entry point. The host fires `paywall_shown`
|
|
32
|
+
// when it presents the page containing this grid.
|
|
33
|
+
//
|
|
34
|
+
// Brand compliance (HARD RULES):
|
|
35
|
+
// - NO payment-processor / infra names in any customer-visible string.
|
|
36
|
+
// - No "Name — descriptor" em-dash AI-voice: the plan NAME is bare
|
|
37
|
+
// ("Bravely Premium") and the plan word ("Annual"/"Lifetime") rides a
|
|
38
|
+
// muted descriptor span.
|
|
39
|
+
//
|
|
40
|
+
// Usage:
|
|
41
|
+
//
|
|
42
|
+
// ```tsx
|
|
43
|
+
// import {
|
|
44
|
+
// OfferSlotGrid,
|
|
45
|
+
// buildOfferSlots,
|
|
46
|
+
// offerThemeForSlug,
|
|
47
|
+
// planTokenForSlot,
|
|
48
|
+
// } from "@bravely-studios/account-web";
|
|
49
|
+
//
|
|
50
|
+
// <OfferSlotGrid
|
|
51
|
+
// slots={buildOfferSlots({ appName: "Scry", appSlug: "scry", type: "RVA" })}
|
|
52
|
+
// theme={offerThemeForSlug("scry")}
|
|
53
|
+
// onSelect={(slot) => {
|
|
54
|
+
// posthog.capture("slot_selected", { offer_slot: telemetryValueForSlot(slot) });
|
|
55
|
+
// manager.openCheckout(planTokenForSlot(slot, "RVA"));
|
|
56
|
+
// }}
|
|
57
|
+
// onSlotViewed={(slot) => posthog.capture("slot_viewed", { offer_slot: telemetryValueForSlot(slot) })}
|
|
58
|
+
// />
|
|
59
|
+
// ```
|
|
60
|
+
import { useEffect, useRef, } from "react";
|
|
61
|
+
// ---- Locked copy constants --------------------------------------------------
|
|
62
|
+
/** The 30-day guarantee label. */
|
|
63
|
+
export const OFFER_GUARANTEE_LINE = "30-Day Money-Back Guarantee";
|
|
64
|
+
/** Hover/disclosure tooltip for the guarantee badge. */
|
|
65
|
+
export const OFFER_GUARANTEE_TOOLTIP = "I-Hate-Your-Apps-Give-Me-My-Money-Back: 30 days, no questions.";
|
|
66
|
+
/** Footer note under the whole grid. */
|
|
67
|
+
export const OFFER_FOOTER_NOTE = "Bravely Studios · one account, every device.";
|
|
68
|
+
/** Footer line inside both bonus blocks. */
|
|
69
|
+
export const OFFER_BONUS_FOOTER = "One sign-in · instant unlock · sync everywhere";
|
|
70
|
+
/**
|
|
71
|
+
* The LOCKED value-stack-dominant tagline (2026-06-01) rendered under the
|
|
72
|
+
* plan name on BOTH bundle slots. Verbatim from `bravely-offer-structure.md`.
|
|
73
|
+
*/
|
|
74
|
+
export const OFFER_BUNDLE_TAGLINE = "all 9 apps, every platform, every device, + the bonus bundle";
|
|
75
|
+
const NUDGE = [
|
|
76
|
+
{ text: "Want the other 9 apps free? " },
|
|
77
|
+
{ text: "Go Annual →", em: "accent" },
|
|
78
|
+
];
|
|
79
|
+
// ---- Per-app themes (verbatim from the get.bravely.dev registry) ------------
|
|
80
|
+
/** Per-app offer themes for the 9 production utilities. */
|
|
81
|
+
export const OFFER_THEMES = {
|
|
82
|
+
scry: { accent: "#a78bfa", accentStrong: "#8b5cf6", cyan: "#22d3ee" },
|
|
83
|
+
printscreenly: { accent: "#ff6b6b", accentStrong: "#e05555", cyan: "#ee5a9f" },
|
|
84
|
+
asapdf: { accent: "#FFD60A", accentStrong: "#F0C000", cyan: "#FB923C" },
|
|
85
|
+
stickily: { accent: "#FFD93D", accentStrong: "#E0BF33", cyan: "#61A8DB" },
|
|
86
|
+
saycopypaste: { accent: "#0EA5E9", accentStrong: "#0284C7", cyan: "#34D399" },
|
|
87
|
+
diskaroo: { accent: "#06b6d4", accentStrong: "#0e7490", cyan: "#3b82f6" },
|
|
88
|
+
terminaltags: { accent: "#d97706", accentStrong: "#b45309", cyan: "#3b9be6" },
|
|
89
|
+
markdly: { accent: "#268559", accentStrong: "#1B6240", cyan: "#5AC8FA" },
|
|
90
|
+
todoingly: { accent: "#3B6EF0", accentStrong: "#1D4ED8", cyan: "#34D399" },
|
|
91
|
+
};
|
|
92
|
+
/**
|
|
93
|
+
* Resolve a theme from the canonical app slug. Falls back to Scry's
|
|
94
|
+
* purple/cyan if the slug is unknown (mirrors the Swift lib).
|
|
95
|
+
*/
|
|
96
|
+
export function offerThemeForSlug(slug) {
|
|
97
|
+
return OFFER_THEMES[slug.toLowerCase()] ?? OFFER_THEMES.scry;
|
|
98
|
+
}
|
|
99
|
+
// ---- Slot ↔ plan/telemetry mapping ------------------------------------------
|
|
100
|
+
/**
|
|
101
|
+
* The catalog plan token `openCheckout()` should send for a slot. Slot-1
|
|
102
|
+
* tokens are interval-true per the 2026-06-10 catalog rename: `monthly` for
|
|
103
|
+
* RVA apps, `onetime` for IVA apps (the server also aliases legacy tokens,
|
|
104
|
+
* but new clients send the canonical key). GSO/FRONT_LTV resolve server-side
|
|
105
|
+
* to the universal bundle plans.
|
|
106
|
+
*/
|
|
107
|
+
export function planTokenForSlot(slot, type) {
|
|
108
|
+
switch (slot) {
|
|
109
|
+
case "HOOK":
|
|
110
|
+
return type === "IVA" ? "onetime" : "monthly";
|
|
111
|
+
case "GSO":
|
|
112
|
+
return "annual";
|
|
113
|
+
case "FRONT_LTV":
|
|
114
|
+
return "lifetime";
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
/** Telemetry value per the count-funnel spec (`offer_slot` property). */
|
|
118
|
+
export function telemetryValueForSlot(slot) {
|
|
119
|
+
switch (slot) {
|
|
120
|
+
case "HOOK":
|
|
121
|
+
return "hook";
|
|
122
|
+
case "GSO":
|
|
123
|
+
return "gso";
|
|
124
|
+
case "FRONT_LTV":
|
|
125
|
+
return "ltv";
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
// ---- Bonus apps (the ordering rule) -----------------------------------------
|
|
129
|
+
const CANONICAL_BONUS_APPS = [
|
|
130
|
+
{ name: "Scry", note: "Remote desktop", slug: "scry" },
|
|
131
|
+
{ name: "PrintScreen.ly", note: "Screenshots & recording", slug: "printscreenly" },
|
|
132
|
+
{ name: "ASAPDF", note: "PDF edit, sign, share", slug: "asapdf" },
|
|
133
|
+
];
|
|
134
|
+
const BONUS_SUBSTITUTE = {
|
|
135
|
+
name: "Diskaroo",
|
|
136
|
+
note: "Disk-space visualizer",
|
|
137
|
+
slug: "diskaroo",
|
|
138
|
+
};
|
|
139
|
+
/**
|
|
140
|
+
* The canonical bonus-bundle example apps, in order: Scry → PrintScreen.ly →
|
|
141
|
+
* ASAPDF, "+ 5 more". Collision rule: if `<app>` IS one of those 3, drop it
|
|
142
|
+
* and append Diskaroo so the customer always sees 3 *other* apps.
|
|
143
|
+
*/
|
|
144
|
+
export function bonusAppsForSlug(slug) {
|
|
145
|
+
const normalized = slug.toLowerCase();
|
|
146
|
+
const apps = CANONICAL_BONUS_APPS.filter((a) => a.slug !== normalized);
|
|
147
|
+
if (apps.length < 3)
|
|
148
|
+
apps.push(BONUS_SUBSTITUTE);
|
|
149
|
+
return apps.slice(0, 3).map((a) => ({ ...a }));
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Build the canonical 3-slot offer copy — the verbatim strings from the
|
|
153
|
+
* locked offer structure, so every app's purchase surface reads identically
|
|
154
|
+
* (only `<App>` swaps). Render a subset by filtering the result (provisioned
|
|
155
|
+
* slots only).
|
|
156
|
+
*/
|
|
157
|
+
export function buildOfferSlots(args) {
|
|
158
|
+
const { appName, appSlug, type } = args;
|
|
159
|
+
const slug = appSlug.toLowerCase();
|
|
160
|
+
const extra = [...(args.extraHookBullets ?? [])];
|
|
161
|
+
// Scry-only extra HOOK bullet (E2E encryption) per the locked reference.
|
|
162
|
+
if (slug === "scry" && !extra.includes("End-to-end encrypted, peer-to-peer")) {
|
|
163
|
+
extra.push("End-to-end encrypted, peer-to-peer");
|
|
164
|
+
}
|
|
165
|
+
const bonusApps = bonusAppsForSlug(slug).map((a) => ({
|
|
166
|
+
...a,
|
|
167
|
+
iconSrc: args.bonusIconSrc?.(a.slug),
|
|
168
|
+
}));
|
|
169
|
+
const hook = type === "RVA"
|
|
170
|
+
? {
|
|
171
|
+
kind: "HOOK",
|
|
172
|
+
name: "Monthly",
|
|
173
|
+
tagline: "Start free",
|
|
174
|
+
priceBig: "$0.00",
|
|
175
|
+
priceUnit: "for 7 days",
|
|
176
|
+
priceSub: [
|
|
177
|
+
{ text: "then " },
|
|
178
|
+
{ text: "$9.99/mo", em: "accent" },
|
|
179
|
+
{ text: " · cancel anytime" },
|
|
180
|
+
],
|
|
181
|
+
bullets: [`Get ${appName} on all platforms`, "Full Pro access", ...extra, "Cancel anytime"],
|
|
182
|
+
nudge: NUDGE,
|
|
183
|
+
cta: "ghost",
|
|
184
|
+
ctaLabel: "Start free",
|
|
185
|
+
}
|
|
186
|
+
: {
|
|
187
|
+
kind: "HOOK",
|
|
188
|
+
name: "One-Time",
|
|
189
|
+
tagline: "Just this app",
|
|
190
|
+
priceBig: "$19.99",
|
|
191
|
+
priceUnit: "once",
|
|
192
|
+
priceSub: [{ text: "yours forever · all platforms" }],
|
|
193
|
+
bullets: [`Get ${appName} on all platforms`, ...extra, "Pay once — no subscription"],
|
|
194
|
+
guarantee: OFFER_GUARANTEE_LINE,
|
|
195
|
+
nudge: NUDGE,
|
|
196
|
+
cta: "ghost",
|
|
197
|
+
ctaLabel: `Get ${appName}`,
|
|
198
|
+
};
|
|
199
|
+
const gso = {
|
|
200
|
+
kind: "GSO",
|
|
201
|
+
badge: "Best Value",
|
|
202
|
+
name: "Bravely Premium",
|
|
203
|
+
nameSub: "Annual",
|
|
204
|
+
tagline: OFFER_BUNDLE_TAGLINE,
|
|
205
|
+
priceBig: "$7.99",
|
|
206
|
+
priceUnit: "/mo",
|
|
207
|
+
priceSub: [{ text: "$95.99 billed annually" }],
|
|
208
|
+
bullets: [`Get ${appName} on all platforms`, "Best per-month price"],
|
|
209
|
+
guarantee: OFFER_GUARANTEE_LINE,
|
|
210
|
+
bonus: {
|
|
211
|
+
label: "Bonus",
|
|
212
|
+
headline: [
|
|
213
|
+
{ text: "FREE full access to " },
|
|
214
|
+
{ text: "9 other premium utilities", em: "cyan" },
|
|
215
|
+
{ text: " — all platforms" },
|
|
216
|
+
],
|
|
217
|
+
apps: bonusApps,
|
|
218
|
+
more: "+ 5 more",
|
|
219
|
+
value: "$500 value",
|
|
220
|
+
footer: OFFER_BONUS_FOOTER,
|
|
221
|
+
},
|
|
222
|
+
cta: "loud",
|
|
223
|
+
ctaLabel: "Get the Best Value",
|
|
224
|
+
highlighted: true,
|
|
225
|
+
};
|
|
226
|
+
const ltv = {
|
|
227
|
+
kind: "FRONT_LTV",
|
|
228
|
+
name: "Bravely Premium",
|
|
229
|
+
nameSub: "Lifetime",
|
|
230
|
+
tagline: OFFER_BUNDLE_TAGLINE,
|
|
231
|
+
priceBig: "$399",
|
|
232
|
+
priceSub: [{ text: "all future updates included" }],
|
|
233
|
+
bullets: [`Get ${appName} on all platforms`, "Pay once, yours forever"],
|
|
234
|
+
guarantee: OFFER_GUARANTEE_LINE,
|
|
235
|
+
bonus: {
|
|
236
|
+
label: "Bonus",
|
|
237
|
+
headline: [
|
|
238
|
+
{ text: "FREE " },
|
|
239
|
+
{ text: "lifetime", em: "accent" },
|
|
240
|
+
{ text: " access to " },
|
|
241
|
+
{ text: "9 other premium utilities", em: "cyan" },
|
|
242
|
+
{ text: " — all platforms" },
|
|
243
|
+
],
|
|
244
|
+
apps: bonusApps.map((a) => ({ ...a })),
|
|
245
|
+
more: "+ 5 more",
|
|
246
|
+
value: "$1,200 value",
|
|
247
|
+
footer: OFFER_BONUS_FOOTER,
|
|
248
|
+
},
|
|
249
|
+
cta: "solid",
|
|
250
|
+
ctaLabel: "Own it for life",
|
|
251
|
+
};
|
|
252
|
+
return [hook, gso, ltv];
|
|
253
|
+
}
|
|
254
|
+
// ---- Viewport fit (spec `commerce.offer_page_fit`, option 3) -----------------
|
|
255
|
+
/** Below this viewport width the cards stack single-column + scroll. */
|
|
256
|
+
export const OFFER_FIT_MIN_WIDTH = 901;
|
|
257
|
+
/** Scale clamp floor — below this the scale floors and the page scrolls. */
|
|
258
|
+
export const OFFER_FIT_MIN_SCALE = 0.5;
|
|
259
|
+
/** Scale clamp ceiling — scale-up allowed to fill large displays. */
|
|
260
|
+
export const OFFER_FIT_MAX_SCALE = 3.0;
|
|
261
|
+
/** Breathing room around the fitted content (px). */
|
|
262
|
+
export const OFFER_FIT_PAD = 24;
|
|
263
|
+
/** The grid's natural design width (px) used as the scale-fit basis. */
|
|
264
|
+
export const OFFER_NATURAL_WIDTH = 1200;
|
|
265
|
+
/**
|
|
266
|
+
* The canonical fit formula (plan §4, verbatim): uniform scale-to-fit BOTH
|
|
267
|
+
* axes, `scale = min(availW/naturalW, availH/naturalH)` clamped to
|
|
268
|
+
* [0.5, 3.0]; below 0.5 the scale floors and the surface falls back to
|
|
269
|
+
* scrolling — never clipping. Pure so tests can pin the math.
|
|
270
|
+
*/
|
|
271
|
+
export function computeOfferFit(input) {
|
|
272
|
+
const pad = input.pad ?? OFFER_FIT_PAD;
|
|
273
|
+
if (input.viewportWidth < OFFER_FIT_MIN_WIDTH)
|
|
274
|
+
return { mode: "stacked" };
|
|
275
|
+
if (!(input.naturalWidth > 0) || !(input.naturalHeight > 0)) {
|
|
276
|
+
return { mode: "fit", scale: 1, scrollFallback: false };
|
|
277
|
+
}
|
|
278
|
+
const raw = Math.min((input.viewportWidth - pad) / input.naturalWidth, (input.viewportHeight - pad) / input.naturalHeight);
|
|
279
|
+
const scale = Math.min(Math.max(raw, OFFER_FIT_MIN_SCALE), OFFER_FIT_MAX_SCALE);
|
|
280
|
+
return { mode: "fit", scale, scrollFallback: raw < OFFER_FIT_MIN_SCALE };
|
|
281
|
+
}
|
|
282
|
+
const SYSTEM_FONT = '-apple-system, BlinkMacSystemFont, "Segoe UI Variable", "Segoe UI", Roboto, "Inter", "Helvetica Neue", Arial, sans-serif';
|
|
283
|
+
/**
|
|
284
|
+
* Render the canonical 3-up offer grid with full-viewport scale-to-fit.
|
|
285
|
+
* Mount it on a near-full-viewport surface; it owns its own scaling.
|
|
286
|
+
*/
|
|
287
|
+
export function OfferSlotGrid(props) {
|
|
288
|
+
const { slots, theme, onSelect, onSlotViewed, header, footerNote = OFFER_FOOTER_NOTE, guaranteeTooltip = OFFER_GUARANTEE_TOOLTIP, fitToViewport = true, naturalWidth = OFFER_NATURAL_WIDTH, isBusy = false, className, containerStyle, } = props;
|
|
289
|
+
const outerRef = useRef(null);
|
|
290
|
+
const innerRef = useRef(null);
|
|
291
|
+
// slot_viewed: once per slot per mount (cards mount together on web).
|
|
292
|
+
const viewedRef = useRef(new Set());
|
|
293
|
+
useEffect(() => {
|
|
294
|
+
for (const slot of slots) {
|
|
295
|
+
if (viewedRef.current.has(slot.kind))
|
|
296
|
+
continue;
|
|
297
|
+
viewedRef.current.add(slot.kind);
|
|
298
|
+
onSlotViewed?.(slot.kind);
|
|
299
|
+
}
|
|
300
|
+
// Fire for newly-added slots only; identity changes of the callback or
|
|
301
|
+
// re-renders of the same slots must not re-fire.
|
|
302
|
+
}, [slots, onSlotViewed]);
|
|
303
|
+
// FitToViewport-style measurement, extended with scale-UP (D3).
|
|
304
|
+
useEffect(() => {
|
|
305
|
+
if (!fitToViewport)
|
|
306
|
+
return;
|
|
307
|
+
const inEl = innerRef.current;
|
|
308
|
+
const outEl = outerRef.current;
|
|
309
|
+
if (!inEl || !outEl || typeof window === "undefined")
|
|
310
|
+
return;
|
|
311
|
+
const fit = () => {
|
|
312
|
+
// Reset to measure the natural size at the design width.
|
|
313
|
+
inEl.style.transform = "";
|
|
314
|
+
outEl.style.height = "";
|
|
315
|
+
// Available width = the smaller of the viewport and the host container
|
|
316
|
+
// (so a padded host can't cause horizontal clipping).
|
|
317
|
+
const outerW = outEl.clientWidth || window.innerWidth;
|
|
318
|
+
const availWidth = Math.min(window.innerWidth, outerW);
|
|
319
|
+
if (computeOfferFit({
|
|
320
|
+
viewportWidth: availWidth,
|
|
321
|
+
viewportHeight: window.innerHeight,
|
|
322
|
+
naturalWidth,
|
|
323
|
+
naturalHeight: 1,
|
|
324
|
+
}).mode === "stacked") {
|
|
325
|
+
inEl.style.width = "";
|
|
326
|
+
return; // natural single-column layout + scroll
|
|
327
|
+
}
|
|
328
|
+
// Lay the grid out at its NATURAL design width (it may exceed the
|
|
329
|
+
// container — the transform below brings it back inside). No max-width
|
|
330
|
+
// clamp: clamping before measuring would shrink the layout and feed
|
|
331
|
+
// the fit math a lie (the old 84rem-cap class of bug).
|
|
332
|
+
inEl.style.width = `${naturalWidth}px`;
|
|
333
|
+
const naturalH = inEl.scrollHeight;
|
|
334
|
+
if (!naturalH)
|
|
335
|
+
return; // not laid out yet (SSR/test DOM)
|
|
336
|
+
const refit = computeOfferFit({
|
|
337
|
+
viewportWidth: availWidth,
|
|
338
|
+
viewportHeight: window.innerHeight,
|
|
339
|
+
naturalWidth,
|
|
340
|
+
naturalHeight: naturalH,
|
|
341
|
+
});
|
|
342
|
+
const scale = refit.mode === "fit" ? refit.scale : 1;
|
|
343
|
+
// Scale about the top-LEFT then translate to center horizontally:
|
|
344
|
+
// when the inner block is wider than its container, `margin: auto`
|
|
345
|
+
// can't center it and a center origin would clip one side.
|
|
346
|
+
const tx = (outerW - naturalWidth * scale) / 2;
|
|
347
|
+
inEl.style.transformOrigin = "top left";
|
|
348
|
+
inEl.style.transform = `translateX(${tx}px) scale(${scale})`;
|
|
349
|
+
outEl.style.height = `${naturalH * scale}px`;
|
|
350
|
+
};
|
|
351
|
+
fit();
|
|
352
|
+
window.addEventListener("resize", fit);
|
|
353
|
+
const t = setTimeout(fit, 150);
|
|
354
|
+
const fonts = document.fonts;
|
|
355
|
+
if (fonts?.ready) {
|
|
356
|
+
void fonts.ready.then(fit).catch(() => undefined);
|
|
357
|
+
}
|
|
358
|
+
return () => {
|
|
359
|
+
window.removeEventListener("resize", fit);
|
|
360
|
+
clearTimeout(t);
|
|
361
|
+
};
|
|
362
|
+
}, [fitToViewport, naturalWidth, slots.length]);
|
|
363
|
+
const vars = {
|
|
364
|
+
["--bvy-accent"]: theme.accent,
|
|
365
|
+
["--bvy-accent-strong"]: theme.accentStrong,
|
|
366
|
+
["--bvy-cyan"]: theme.cyan,
|
|
367
|
+
fontFamily: SYSTEM_FONT,
|
|
368
|
+
color: "#f5f3ff",
|
|
369
|
+
width: "100%",
|
|
370
|
+
...containerStyle,
|
|
371
|
+
};
|
|
372
|
+
return (_jsxs("div", { className: className, style: vars, "data-bravely-component": "offer-slot-grid", "data-bravely-offer-grid": "", children: [_jsx("style", { children: OFFER_GRID_CSS }), _jsx("div", { ref: outerRef, style: { overflow: "hidden", width: "100%" }, children: _jsxs("div", { ref: innerRef, children: [header, _jsx("div", { className: "bvy-offer-grid", children: slots.map((slot) => (_jsx(SlotCard, { slot: slot, guaranteeTooltip: guaranteeTooltip, isBusy: isBusy, onSelect: onSelect }, slot.kind))) }), footerNote ? _jsx("div", { className: "bvy-offer-footnote", children: footerNote }) : null] }) })] }));
|
|
373
|
+
}
|
|
374
|
+
// ---- Internals ------------------------------------------------------------------
|
|
375
|
+
function RichText({ parts }) {
|
|
376
|
+
return (_jsx(_Fragment, { children: parts.map((p, i) => p.em ? (_jsx("span", { className: p.em === "accent" ? "bvy-em-accent" : "bvy-em-cyan", children: p.text }, i)) : (_jsx("span", { children: p.text }, i))) }));
|
|
377
|
+
}
|
|
378
|
+
function CheckIcon() {
|
|
379
|
+
return (_jsx("svg", { "aria-hidden": true, viewBox: "0 0 20 20", fill: "currentColor", children: _jsx("path", { d: "M16.7 5.3a1 1 0 0 1 0 1.4l-7.5 7.5a1 1 0 0 1-1.4 0L3.3 9.7a1 1 0 1 1 1.4-1.4l3.1 3.1 6.8-6.8a1 1 0 0 1 1.1-.3z" }) }));
|
|
380
|
+
}
|
|
381
|
+
function ShieldIcon() {
|
|
382
|
+
return (_jsxs("svg", { "aria-hidden": true, width: "15", height: "15", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round", children: [_jsx("path", { d: "M12 3l7 3v6c0 4.5-3 7.5-7 9-4-1.5-7-4.5-7-9V6z" }), _jsx("path", { d: "M9 12l2 2 4-4" })] }));
|
|
383
|
+
}
|
|
384
|
+
function Sparkle() {
|
|
385
|
+
return (_jsx("svg", { "aria-hidden": true, viewBox: "0 0 24 24", fill: "currentColor", children: _jsx("path", { d: "M12 2l1.7 5.6L19.3 9.3l-5.6 1.7L12 16.6l-1.7-5.6L4.7 9.3l5.6-1.7z" }) }));
|
|
386
|
+
}
|
|
387
|
+
function SlotCard({ slot, guaranteeTooltip, isBusy, onSelect, }) {
|
|
388
|
+
return (_jsxs("div", { className: `bvy-offer-card${slot.highlighted ? " bvy-gso" : ""}`, "data-bravely-slot": slot.kind, children: [slot.badge && _jsx("span", { className: "bvy-best-badge", children: slot.badge }), _jsxs("div", { className: "bvy-plan-name", children: [slot.name, slot.nameSub && _jsx("span", { className: "bvy-plan-name-sub", children: slot.nameSub })] }), _jsx("span", { className: "bvy-plan-tag", children: slot.tagline }), _jsxs("div", { className: "bvy-price", children: [_jsx("span", { className: "bvy-price-big", children: slot.priceBig }), slot.priceUnit && _jsx("span", { className: "bvy-price-unit", children: slot.priceUnit })] }), slot.priceSub && (_jsx("div", { className: "bvy-price-sub", children: _jsx(RichText, { parts: slot.priceSub }) })), _jsx("ul", { className: "bvy-offer-bullets", children: slot.bullets.map((b) => (_jsxs("li", { children: [_jsx(CheckIcon, {}), _jsx("span", { children: b })] }, b))) }), slot.guarantee && (_jsxs("div", { className: "bvy-offer-guarantee", title: guaranteeTooltip, children: [_jsx(ShieldIcon, {}), slot.guarantee] })), slot.bonus && (_jsxs("div", { className: "bvy-offer-bonus", children: [_jsxs("span", { className: "bvy-bonus-tag", children: [_jsx(Sparkle, {}), slot.bonus.label] }), _jsx("div", { className: "bvy-bonus-head", children: _jsx(RichText, { parts: slot.bonus.headline }) }), slot.bonus.apps.map((a) => (_jsxs("div", { className: "bvy-bonus-app", children: [_jsx("span", { className: "bvy-bonus-ic", children: a.iconSrc ? (_jsx("img", { src: a.iconSrc, alt: `${a.name} icon`, width: 40, height: 40 })) : (_jsx("span", { className: "bvy-bonus-monogram", "aria-hidden": true, children: a.name.slice(0, 1) })) }), _jsxs("span", { children: [_jsx("span", { className: "bvy-bonus-app-name", children: a.name }), _jsx("br", {}), _jsx("span", { className: "bvy-bonus-app-desc", children: a.note })] })] }, a.slug))), _jsx("div", { className: "bvy-bonus-more", children: slot.bonus.more }), _jsx("span", { className: "bvy-value-pill", children: slot.bonus.value }), _jsx("div", { className: "bvy-value-foot", children: slot.bonus.footer })] })), slot.nudge && (_jsx("div", { className: "bvy-offer-nudge", children: _jsx(RichText, { parts: slot.nudge }) })), _jsx("div", { className: "bvy-offer-spacer" }), _jsx("div", { className: "bvy-cta-wrap", children: _jsx("button", { type: "button", className: `bvy-cta${slot.cta === "ghost" ? " bvy-ghost" : slot.cta === "loud" ? " bvy-loud" : ""}`, disabled: isBusy, onClick: () => onSelect(slot.kind), "aria-label": slot.ctaLabel, "data-bravely-slot-cta": slot.kind, children: slot.ctaLabel }) })] }));
|
|
389
|
+
}
|
|
390
|
+
// Faithful translation of the get.bravely.dev offer CSS (globals.css), scoped
|
|
391
|
+
// under the component's data attribute with `bvy-` class prefixes so host
|
|
392
|
+
// styles can't collide. Theme colors ride the --bvy-* custom properties.
|
|
393
|
+
const OFFER_GRID_CSS = `
|
|
394
|
+
[data-bravely-offer-grid] .bvy-offer-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; align-items: stretch; }
|
|
395
|
+
@media (max-width: 900px) { [data-bravely-offer-grid] .bvy-offer-grid { grid-template-columns: 1fr; max-width: 460px; margin: 0 auto; gap: 16px; } }
|
|
396
|
+
@media (max-width: 560px) {
|
|
397
|
+
[data-bravely-offer-grid] .bvy-offer-card { padding: 24px 18px 20px; border-radius: 18px; }
|
|
398
|
+
[data-bravely-offer-grid] .bvy-price-big { font-size: 36px; }
|
|
399
|
+
[data-bravely-offer-grid] .bvy-bonus-head { font-size: 14.5px; }
|
|
400
|
+
}
|
|
401
|
+
[data-bravely-offer-grid] .bvy-offer-card {
|
|
402
|
+
position: relative; display: flex; flex-direction: column;
|
|
403
|
+
background: linear-gradient(180deg, #1e153f, #190f36);
|
|
404
|
+
border: 1px solid rgba(167, 139, 250, 0.18); border-radius: 20px;
|
|
405
|
+
padding: 30px 24px 24px; box-shadow: 0 20px 50px rgba(0, 0, 0, 0.45);
|
|
406
|
+
color: #f5f3ff;
|
|
407
|
+
}
|
|
408
|
+
[data-bravely-offer-grid] .bvy-offer-card.bvy-gso {
|
|
409
|
+
border: 2px solid var(--bvy-accent-strong);
|
|
410
|
+
background:
|
|
411
|
+
radial-gradient(420px 220px at 50% -40px, rgba(34, 211, 238, 0.12), rgba(34, 211, 238, 0) 70%),
|
|
412
|
+
linear-gradient(180deg, #241852, #190f36);
|
|
413
|
+
box-shadow: 0 0 0 4px rgba(139, 92, 246, 0.16), 0 30px 70px rgba(139, 92, 246, 0.3);
|
|
414
|
+
}
|
|
415
|
+
[data-bravely-offer-grid] .bvy-best-badge {
|
|
416
|
+
position: absolute; top: -14px; left: 50%; transform: translateX(-50%);
|
|
417
|
+
background: linear-gradient(90deg, var(--bvy-cyan), var(--bvy-accent));
|
|
418
|
+
color: #0b0716; font-weight: 800; font-size: 12px; letter-spacing: 0.14em; text-transform: uppercase;
|
|
419
|
+
padding: 7px 18px; border-radius: 999px; box-shadow: 0 8px 22px rgba(34, 211, 238, 0.4); white-space: nowrap;
|
|
420
|
+
}
|
|
421
|
+
[data-bravely-offer-grid] .bvy-plan-name { font-size: 24px; font-weight: 800; letter-spacing: -0.01em; margin-top: 2px; }
|
|
422
|
+
[data-bravely-offer-grid] .bvy-plan-name-sub { margin-left: 8px; font-weight: 400; color: #8b82a8; }
|
|
423
|
+
[data-bravely-offer-grid] .bvy-plan-tag { display: block; color: #8b82a8; font-size: 14.5px; margin-top: 4px; min-height: 18px; }
|
|
424
|
+
[data-bravely-offer-grid] .bvy-price { margin: 16px 0 4px; display: flex; align-items: baseline; gap: 6px; flex-wrap: wrap; }
|
|
425
|
+
[data-bravely-offer-grid] .bvy-price-big { font-size: 42px; font-weight: 800; letter-spacing: -0.03em; line-height: 1; }
|
|
426
|
+
[data-bravely-offer-grid] .bvy-gso .bvy-price-big { color: var(--bvy-cyan); }
|
|
427
|
+
[data-bravely-offer-grid] .bvy-price-unit { font-size: 18px; font-weight: 700; color: #8b82a8; }
|
|
428
|
+
[data-bravely-offer-grid] .bvy-price-sub { color: #8b82a8; font-size: 14.5px; }
|
|
429
|
+
[data-bravely-offer-grid] .bvy-em-accent { color: var(--bvy-accent); font-weight: 800; }
|
|
430
|
+
[data-bravely-offer-grid] .bvy-em-cyan { color: var(--bvy-cyan); font-weight: 800; }
|
|
431
|
+
[data-bravely-offer-grid] .bvy-offer-bullets { list-style: none; margin: 16px 0 0; padding: 0; display: flex; flex-direction: column; gap: 10px; }
|
|
432
|
+
[data-bravely-offer-grid] .bvy-offer-bullets li { display: flex; gap: 9px; align-items: flex-start; font-size: 15.5px; color: #e7e2ff; }
|
|
433
|
+
[data-bravely-offer-grid] .bvy-offer-bullets li svg { width: 18px; height: 18px; flex: 0 0 auto; margin-top: 1px; color: var(--bvy-cyan); }
|
|
434
|
+
[data-bravely-offer-grid] .bvy-offer-guarantee {
|
|
435
|
+
display: flex; align-items: center; gap: 8px; margin-top: 16px;
|
|
436
|
+
background: rgba(52, 211, 153, 0.1); border: 1px solid rgba(52, 211, 153, 0.32); color: #34d399;
|
|
437
|
+
font-size: 13.5px; font-weight: 700; padding: 9px 12px; border-radius: 10px;
|
|
438
|
+
}
|
|
439
|
+
[data-bravely-offer-grid] .bvy-offer-bonus {
|
|
440
|
+
position: relative; margin-top: 24px;
|
|
441
|
+
background: linear-gradient(180deg, rgba(34, 211, 238, 0.06), rgba(139, 92, 246, 0.05));
|
|
442
|
+
border: 1.5px dashed rgba(34, 211, 238, 0.45); border-radius: 16px; padding: 28px 16px 16px;
|
|
443
|
+
}
|
|
444
|
+
[data-bravely-offer-grid] .bvy-bonus-tag {
|
|
445
|
+
position: absolute; top: -15px; left: 50%; transform: translateX(-50%) rotate(-2deg);
|
|
446
|
+
display: inline-flex; align-items: center; gap: 7px;
|
|
447
|
+
background: linear-gradient(95deg, var(--bvy-accent-strong), var(--bvy-cyan));
|
|
448
|
+
color: #0b0716; font-weight: 900; font-size: 14px; letter-spacing: 0.22em; text-transform: uppercase; padding: 8px 22px;
|
|
449
|
+
clip-path: polygon(8px 0, calc(100% - 8px) 0, 100% 50%, calc(100% - 8px) 100%, 8px 100%, 0 50%);
|
|
450
|
+
box-shadow: 0 10px 26px rgba(34, 211, 238, 0.45); text-shadow: 0 1px 0 rgba(255, 255, 255, 0.25);
|
|
451
|
+
}
|
|
452
|
+
[data-bravely-offer-grid] .bvy-bonus-tag svg { width: 14px; height: 14px; }
|
|
453
|
+
[data-bravely-offer-grid] .bvy-bonus-head { text-align: center; font-size: 15.5px; font-weight: 800; line-height: 1.35; color: #f5f3ff; margin: 2px 6px 14px; }
|
|
454
|
+
[data-bravely-offer-grid] .bvy-bonus-app { display: flex; gap: 11px; align-items: center; padding: 8px 6px; }
|
|
455
|
+
[data-bravely-offer-grid] .bvy-bonus-app + .bvy-bonus-app { border-top: 1px solid rgba(167, 139, 250, 0.12); }
|
|
456
|
+
[data-bravely-offer-grid] .bvy-bonus-ic {
|
|
457
|
+
flex: 0 0 auto; width: 40px; height: 40px; border-radius: 10px; overflow: hidden;
|
|
458
|
+
display: flex; align-items: center; justify-content: center;
|
|
459
|
+
background: rgba(167, 139, 250, 0.08); box-shadow: inset 0 0 0 1px rgba(167, 139, 250, 0.2);
|
|
460
|
+
}
|
|
461
|
+
[data-bravely-offer-grid] .bvy-bonus-ic img { width: 100%; height: 100%; object-fit: cover; display: block; }
|
|
462
|
+
[data-bravely-offer-grid] .bvy-bonus-monogram { font-size: 16px; font-weight: 800; color: var(--bvy-accent); }
|
|
463
|
+
[data-bravely-offer-grid] .bvy-bonus-app-name { font-size: 15.5px; font-weight: 800; }
|
|
464
|
+
[data-bravely-offer-grid] .bvy-bonus-app-desc { font-size: 13px; color: #8b82a8; }
|
|
465
|
+
[data-bravely-offer-grid] .bvy-bonus-more { font-size: 14px; font-weight: 800; color: var(--bvy-accent); text-align: center; padding: 8px; }
|
|
466
|
+
[data-bravely-offer-grid] .bvy-value-pill {
|
|
467
|
+
display: block; text-align: center; margin: 12px auto 0; width: max-content;
|
|
468
|
+
background: linear-gradient(90deg, var(--bvy-accent-strong), var(--bvy-cyan)); color: #0b0716;
|
|
469
|
+
font-weight: 900; font-size: 22px; padding: 8px 24px; border-radius: 999px; box-shadow: 0 8px 20px rgba(139, 92, 246, 0.4);
|
|
470
|
+
}
|
|
471
|
+
[data-bravely-offer-grid] .bvy-value-foot { text-align: center; font-size: 12.5px; color: #8b82a8; margin-top: 10px; }
|
|
472
|
+
[data-bravely-offer-grid] .bvy-offer-nudge {
|
|
473
|
+
margin-top: 20px; text-align: center; font-size: 12.5px; color: #8b82a8;
|
|
474
|
+
border: 1px dashed rgba(167, 139, 250, 0.25); border-radius: 12px; padding: 12px;
|
|
475
|
+
}
|
|
476
|
+
[data-bravely-offer-grid] .bvy-offer-spacer { flex: 1 1 auto; }
|
|
477
|
+
[data-bravely-offer-grid] .bvy-cta-wrap { margin-top: 22px; }
|
|
478
|
+
[data-bravely-offer-grid] .bvy-cta {
|
|
479
|
+
display: flex; align-items: center; justify-content: center; gap: 8px; width: 100%;
|
|
480
|
+
border: 0; cursor: pointer; font-family: inherit; font-weight: 800; font-size: 16.5px; padding: 15px 18px;
|
|
481
|
+
border-radius: 13px; color: #0b0716; background: linear-gradient(90deg, var(--bvy-accent), var(--bvy-accent-strong));
|
|
482
|
+
box-shadow: 0 12px 28px rgba(139, 92, 246, 0.35); transition: transform 0.12s ease;
|
|
483
|
+
}
|
|
484
|
+
[data-bravely-offer-grid] .bvy-cta.bvy-ghost { background: transparent; color: #f5f3ff; border: 1.5px solid rgba(167, 139, 250, 0.4); box-shadow: none; }
|
|
485
|
+
[data-bravely-offer-grid] .bvy-cta.bvy-loud { background: linear-gradient(90deg, var(--bvy-cyan), var(--bvy-accent)); font-size: 17.5px; box-shadow: 0 14px 34px rgba(34, 211, 238, 0.42); }
|
|
486
|
+
[data-bravely-offer-grid] .bvy-cta:hover { transform: translateY(-2px); }
|
|
487
|
+
[data-bravely-offer-grid] .bvy-cta:disabled { opacity: 0.7; cursor: default; transform: none; }
|
|
488
|
+
[data-bravely-offer-grid] .bvy-offer-footnote { margin-top: 28px; text-align: center; font-size: 12px; color: #8b82a8; }
|
|
489
|
+
`;
|
|
490
|
+
//# sourceMappingURL=OfferSlotGrid.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"OfferSlotGrid.js","sourceRoot":"","sources":["../../src/components/OfferSlotGrid.tsx"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export { BravelyAccountManager, BravelyClientKilledError, OAuthError } from "./BravelyAccountManager.js";
|
|
2
|
-
export type { ActivationResult } from "./BravelyAccountManager.js";
|
|
1
|
+
export { BravelyAccountManager, BravelyClientKilledError, OAuthError, PRE_EXPIRY_REFRESH_WINDOW_MS, } from "./BravelyAccountManager.js";
|
|
2
|
+
export type { ActivationResult, RefreshOutcome } from "./BravelyAccountManager.js";
|
|
3
3
|
export { EntitlementCache, ENTITLEMENT_CACHE_TTL_SECONDS } from "./EntitlementCache.js";
|
|
4
4
|
export { ActivationStateMachine, AUTO_ADVANCE_MS, AUTO_ADVANCE_TO, POST_CHECKOUT_RETRY, type ActivationEvent, } from "./ActivationStateMachine.js";
|
|
5
5
|
export { parseDeprecation } from "./deprecation.js";
|
|
@@ -14,4 +14,7 @@ export { BravelyProviderButtons, type BravelyProviderButtonsProps, type BravelyP
|
|
|
14
14
|
export { useActivationLaneFromUrl, detectActivationLane, type ActivationLaneResult, type ActivationLaneSource, type UseActivationLaneFromUrlOptions, } from "./hooks/useActivationLaneFromUrl.js";
|
|
15
15
|
export { useFreshLaunchRestoration, renderFreshLaunchToastCopy, type FreshLaunchRestorationResult, type UseFreshLaunchRestorationOptions, } from "./hooks/useFreshLaunchRestoration.js";
|
|
16
16
|
export { displayNameFor, DISPLAY_NAMES } from "./displayName.js";
|
|
17
|
+
export { BravelySignInScreen, SIGN_IN_OFFLINE_HEADLINE, SIGN_IN_OFFLINE_BODY, SIGN_IN_OFFLINE_RETRY_LABEL, type BravelySignInScreenProps, } from "./components/BravelySignInScreen.js";
|
|
18
|
+
export { OfferSlotGrid, buildOfferSlots, bonusAppsForSlug, offerThemeForSlug, planTokenForSlot, telemetryValueForSlot, computeOfferFit, OFFER_THEMES, OFFER_GUARANTEE_LINE, OFFER_GUARANTEE_TOOLTIP, OFFER_FOOTER_NOTE, OFFER_BONUS_FOOTER, OFFER_BUNDLE_TAGLINE, OFFER_FIT_MIN_WIDTH, OFFER_FIT_MIN_SCALE, OFFER_FIT_MAX_SCALE, OFFER_FIT_PAD, OFFER_NATURAL_WIDTH, type OfferSlotKind, type OfferAppType, type OfferCtaVariant, type OfferRich, type OfferRichSeg, type OfferBonusApp, type OfferBonus, type OfferSlotCopy, type OfferTheme, type OfferSlotGridProps, type BuildOfferSlotsArgs, type OfferFitInput, type OfferFitResult, } from "./components/OfferSlotGrid.js";
|
|
19
|
+
export { getOrMintInstallId, emitAppFirstOpenedIfNeeded, INSTALL_ID_STORAGE_KEY, FIRST_OPEN_SENTINEL_STORAGE_KEY, type FirstOpenResult, type EmitAppFirstOpenedOptions, } from "./installMetrics.js";
|
|
17
20
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,qBAAqB,EACrB,wBAAwB,EACxB,UAAU,EACV,4BAA4B,GAC7B,MAAM,4BAA4B,CAAC;AACpC,YAAY,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AACnF,OAAO,EAAE,gBAAgB,EAAE,6BAA6B,EAAE,MAAM,uBAAuB,CAAC;AACxF,OAAO,EACL,sBAAsB,EACtB,eAAe,EACf,eAAe,EACf,mBAAmB,EACnB,KAAK,eAAe,GACrB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EACL,oBAAoB,EACpB,qBAAqB,EACrB,aAAa,EACb,iBAAiB,EACjB,aAAa,EACb,WAAW,EACX,eAAe,EACf,eAAe,GAChB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,oBAAoB,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACtH,YAAY,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EACL,eAAe,EACf,oBAAoB,EACpB,aAAa,EACb,eAAe,EACf,KAAK,WAAW,GACjB,MAAM,WAAW,CAAC;AACnB,YAAY,EACV,OAAO,EACP,WAAW,EACX,mBAAmB,EACnB,mBAAmB,EACnB,cAAc,EACd,kBAAkB,EAClB,WAAW,EACX,mBAAmB,EACnB,eAAe,EACf,mBAAmB,EACnB,aAAa,EACb,gBAAgB,EAChB,oBAAoB,EACpB,mBAAmB,EACnB,iBAAiB,EACjB,YAAY,EACZ,mBAAmB,EACnB,kBAAkB,EAClB,SAAS,GACV,MAAM,YAAY,CAAC;AAGpB,OAAO,EACL,gBAAgB,EAChB,iCAAiC,EACjC,qBAAqB,EACrB,gBAAgB,EAChB,mBAAmB,EACnB,KAAK,qBAAqB,EAC1B,KAAK,qBAAqB,GAC3B,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EACL,YAAY,EACZ,0BAA0B,EAC1B,yBAAyB,EACzB,kBAAkB,EAClB,KAAK,iBAAiB,GACvB,MAAM,8BAA8B,CAAC;AACtC,OAAO,EACL,sBAAsB,EACtB,KAAK,2BAA2B,EAChC,KAAK,0BAA0B,EAC/B,KAAK,YAAY,GAClB,MAAM,wCAAwC,CAAC;AAChD,OAAO,EACL,wBAAwB,EACxB,oBAAoB,EACpB,KAAK,oBAAoB,EACzB,KAAK,oBAAoB,EACzB,KAAK,+BAA+B,GACrC,MAAM,qCAAqC,CAAC;AAC7C,OAAO,EACL,yBAAyB,EACzB,0BAA0B,EAC1B,KAAK,4BAA4B,EACjC,KAAK,gCAAgC,GACtC,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAIjE,OAAO,EACL,mBAAmB,EACnB,wBAAwB,EACxB,oBAAoB,EACpB,2BAA2B,EAC3B,KAAK,wBAAwB,GAC9B,MAAM,qCAAqC,CAAC;AAC7C,OAAO,EACL,aAAa,EACb,eAAe,EACf,gBAAgB,EAChB,iBAAiB,EACjB,gBAAgB,EAChB,qBAAqB,EACrB,eAAe,EACf,YAAY,EACZ,oBAAoB,EACpB,uBAAuB,EACvB,iBAAiB,EACjB,kBAAkB,EAClB,oBAAoB,EACpB,mBAAmB,EACnB,mBAAmB,EACnB,mBAAmB,EACnB,aAAa,EACb,mBAAmB,EACnB,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,KAAK,eAAe,EACpB,KAAK,SAAS,EACd,KAAK,YAAY,EACjB,KAAK,aAAa,EAClB,KAAK,UAAU,EACf,KAAK,aAAa,EAClB,KAAK,UAAU,EACf,KAAK,kBAAkB,EACvB,KAAK,mBAAmB,EACxB,KAAK,aAAa,EAClB,KAAK,cAAc,GACpB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EACL,kBAAkB,EAClB,0BAA0B,EAC1B,sBAAsB,EACtB,+BAA+B,EAC/B,KAAK,eAAe,EACpB,KAAK,yBAAyB,GAC/B,MAAM,qBAAqB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// Barrel re-exports for `@bravely-studios/account-web`.
|
|
2
|
-
export { BravelyAccountManager, BravelyClientKilledError, OAuthError } from "./BravelyAccountManager.js";
|
|
2
|
+
export { BravelyAccountManager, BravelyClientKilledError, OAuthError, PRE_EXPIRY_REFRESH_WINDOW_MS, } from "./BravelyAccountManager.js";
|
|
3
3
|
export { EntitlementCache, ENTITLEMENT_CACHE_TTL_SECONDS } from "./EntitlementCache.js";
|
|
4
4
|
export { ActivationStateMachine, AUTO_ADVANCE_MS, AUTO_ADVANCE_TO, POST_CHECKOUT_RETRY, } from "./ActivationStateMachine.js";
|
|
5
5
|
export { parseDeprecation } from "./deprecation.js";
|
|
@@ -13,4 +13,9 @@ export { BravelyProviderButtons, } from "./components/BravelyProviderButtons.js"
|
|
|
13
13
|
export { useActivationLaneFromUrl, detectActivationLane, } from "./hooks/useActivationLaneFromUrl.js";
|
|
14
14
|
export { useFreshLaunchRestoration, renderFreshLaunchToastCopy, } from "./hooks/useFreshLaunchRestoration.js";
|
|
15
15
|
export { displayNameFor, DISPLAY_NAMES } from "./displayName.js";
|
|
16
|
+
// ---- Login-first cutover surfaces (0.4.0: D1 sign-in screen, D3 offer grid,
|
|
17
|
+
// ---- D6 install metrics) ----------------------------------------------------
|
|
18
|
+
export { BravelySignInScreen, SIGN_IN_OFFLINE_HEADLINE, SIGN_IN_OFFLINE_BODY, SIGN_IN_OFFLINE_RETRY_LABEL, } from "./components/BravelySignInScreen.js";
|
|
19
|
+
export { OfferSlotGrid, buildOfferSlots, bonusAppsForSlug, offerThemeForSlug, planTokenForSlot, telemetryValueForSlot, computeOfferFit, OFFER_THEMES, OFFER_GUARANTEE_LINE, OFFER_GUARANTEE_TOOLTIP, OFFER_FOOTER_NOTE, OFFER_BONUS_FOOTER, OFFER_BUNDLE_TAGLINE, OFFER_FIT_MIN_WIDTH, OFFER_FIT_MIN_SCALE, OFFER_FIT_MAX_SCALE, OFFER_FIT_PAD, OFFER_NATURAL_WIDTH, } from "./components/OfferSlotGrid.js";
|
|
20
|
+
export { getOrMintInstallId, emitAppFirstOpenedIfNeeded, INSTALL_ID_STORAGE_KEY, FIRST_OPEN_SENTINEL_STORAGE_KEY, } from "./installMetrics.js";
|
|
16
21
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,wDAAwD;AAExD,OAAO,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,wDAAwD;AAExD,OAAO,EACL,qBAAqB,EACrB,wBAAwB,EACxB,UAAU,EACV,4BAA4B,GAC7B,MAAM,4BAA4B,CAAC;AAEpC,OAAO,EAAE,gBAAgB,EAAE,6BAA6B,EAAE,MAAM,uBAAuB,CAAC;AACxF,OAAO,EACL,sBAAsB,EACtB,eAAe,EACf,eAAe,EACf,mBAAmB,GAEpB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EACL,oBAAoB,EACpB,qBAAqB,EACrB,aAAa,EACb,iBAAiB,EACjB,aAAa,EACb,WAAW,EACX,eAAe,EACf,eAAe,GAChB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,oBAAoB,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAEtH,OAAO,EACL,eAAe,EACf,oBAAoB,EACpB,aAAa,EACb,eAAe,GAEhB,MAAM,WAAW,CAAC;AAuBnB,+EAA+E;AAC/E,OAAO,EACL,gBAAgB,EAChB,iCAAiC,EACjC,qBAAqB,EACrB,gBAAgB,EAChB,mBAAmB,GAGpB,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EACL,YAAY,EACZ,0BAA0B,EAC1B,yBAAyB,EACzB,kBAAkB,GAEnB,MAAM,8BAA8B,CAAC;AACtC,OAAO,EACL,sBAAsB,GAIvB,MAAM,wCAAwC,CAAC;AAChD,OAAO,EACL,wBAAwB,EACxB,oBAAoB,GAIrB,MAAM,qCAAqC,CAAC;AAC7C,OAAO,EACL,yBAAyB,EACzB,0BAA0B,GAG3B,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEjE,8EAA8E;AAC9E,gFAAgF;AAChF,OAAO,EACL,mBAAmB,EACnB,wBAAwB,EACxB,oBAAoB,EACpB,2BAA2B,GAE5B,MAAM,qCAAqC,CAAC;AAC7C,OAAO,EACL,aAAa,EACb,eAAe,EACf,gBAAgB,EAChB,iBAAiB,EACjB,gBAAgB,EAChB,qBAAqB,EACrB,eAAe,EACf,YAAY,EACZ,oBAAoB,EACpB,uBAAuB,EACvB,iBAAiB,EACjB,kBAAkB,EAClB,oBAAoB,EACpB,mBAAmB,EACnB,mBAAmB,EACnB,mBAAmB,EACnB,aAAa,EACb,mBAAmB,GAcpB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EACL,kBAAkB,EAClB,0BAA0B,EAC1B,sBAAsB,EACtB,+BAA+B,GAGhC,MAAM,qBAAqB,CAAC"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { type Storage } from "./storage.js";
|
|
2
|
+
/** Storage key for the per-install UUID (persistent / IndexedDB). */
|
|
3
|
+
export declare const INSTALL_ID_STORAGE_KEY = "install_id";
|
|
4
|
+
/** Storage key for the `app_first_opened` fire-once sentinel (persistent / IndexedDB). */
|
|
5
|
+
export declare const FIRST_OPEN_SENTINEL_STORAGE_KEY = "first_open_sentinel";
|
|
6
|
+
/**
|
|
7
|
+
* Return the per-install UUID, minting + persisting it on first call.
|
|
8
|
+
* Stable for the life of the install (origin storage); cleared only when the
|
|
9
|
+
* user clears site data — which IS the reinstall boundary on web.
|
|
10
|
+
*/
|
|
11
|
+
export declare function getOrMintInstallId(storage?: Storage): Promise<string>;
|
|
12
|
+
/** Result of `emitAppFirstOpenedIfNeeded()`. */
|
|
13
|
+
export interface FirstOpenResult {
|
|
14
|
+
/** True iff this call was the first open (sentinel was absent and the emit ran). */
|
|
15
|
+
fired: boolean;
|
|
16
|
+
/** The per-install UUID (minted here if needed) — attach it to the event. */
|
|
17
|
+
installId: string;
|
|
18
|
+
}
|
|
19
|
+
export interface EmitAppFirstOpenedOptions {
|
|
20
|
+
/**
|
|
21
|
+
* Host-provided emitter — fire the `app_first_opened` analytics event here
|
|
22
|
+
* (exact name; PostHog or the app's standard layer). Called AFTER the
|
|
23
|
+
* sentinel is persisted; a throw is swallowed (under-count, never
|
|
24
|
+
* double-fire). When analytics is opted out / unconfigured, pass a no-op:
|
|
25
|
+
* the sentinel is still written so keys appearing later can't re-fire it.
|
|
26
|
+
*/
|
|
27
|
+
emit: (ctx: {
|
|
28
|
+
installId: string;
|
|
29
|
+
}) => void | Promise<void>;
|
|
30
|
+
/** Storage override (testing / custom adapters). */
|
|
31
|
+
storage?: Storage;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Fire-once `app_first_opened` guard. Call at app entry, before any other
|
|
35
|
+
* UI/flow gating (NOT behind onboarding or sign-in). Persist-first contract:
|
|
36
|
+
* the sentinel row is written before `emit` runs. Concurrent calls are
|
|
37
|
+
* serialized per storage adapter (exactly one can fire).
|
|
38
|
+
*/
|
|
39
|
+
export declare function emitAppFirstOpenedIfNeeded(opts: EmitAppFirstOpenedOptions): Promise<FirstOpenResult>;
|
|
40
|
+
//# sourceMappingURL=installMetrics.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"installMetrics.d.ts","sourceRoot":"","sources":["../src/installMetrics.ts"],"names":[],"mappings":"AA0BA,OAAO,EAAkB,KAAK,OAAO,EAAE,MAAM,cAAc,CAAC;AAE5D,qEAAqE;AACrE,eAAO,MAAM,sBAAsB,eAAe,CAAC;AACnD,0FAA0F;AAC1F,eAAO,MAAM,+BAA+B,wBAAwB,CAAC;AAsBrE;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,GAAE,OAAgC,GAAG,OAAO,CAAC,MAAM,CAAC,CAc7F;AAED,gDAAgD;AAChD,MAAM,WAAW,eAAe;IAC9B,oFAAoF;IACpF,KAAK,EAAE,OAAO,CAAC;IACf,6EAA6E;IAC7E,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,yBAAyB;IACxC;;;;;;OAMG;IACH,IAAI,EAAE,CAAC,GAAG,EAAE;QAAE,SAAS,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3D,oDAAoD;IACpD,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAUD;;;;;GAKG;AACH,wBAAgB,0BAA0B,CACxC,IAAI,EAAE,yBAAyB,GAC9B,OAAO,CAAC,eAAe,CAAC,CAuB1B"}
|