@growth-operations/ui-shared 1.6.5 → 1.6.7
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/package.json +1 -1
- package/src/billing/BillingTab.jsx +23 -6
- package/src/billing/PlanGrid.jsx +44 -7
- package/src/home/HealthHero.jsx +11 -0
package/package.json
CHANGED
|
@@ -138,7 +138,7 @@ function StatusPanel({ entitlement }) {
|
|
|
138
138
|
);
|
|
139
139
|
}
|
|
140
140
|
|
|
141
|
-
function TrialSubscriptionBilling({ context, state, appKey }) {
|
|
141
|
+
function TrialSubscriptionBilling({ context, state, appKey, openIframe = null }) {
|
|
142
142
|
const ent = state?.entitlement;
|
|
143
143
|
|
|
144
144
|
// Install not provisioned with a Stripe customer yet — calm "finish setup"
|
|
@@ -232,13 +232,14 @@ function TrialSubscriptionBilling({ context, state, appKey }) {
|
|
|
232
232
|
ctaLabel="Upgrade to"
|
|
233
233
|
heading="Your plan"
|
|
234
234
|
footnote="Upgrade any time during your trial — your trial end date stays the same, and the new tier applies when it converts. To move to a lower tier, talk to sales."
|
|
235
|
+
openIframe={openIframe}
|
|
235
236
|
/>
|
|
236
237
|
)}
|
|
237
238
|
</Flex>
|
|
238
239
|
);
|
|
239
240
|
}
|
|
240
241
|
|
|
241
|
-
function CreditsBilling({ context, state, appKey }) {
|
|
242
|
+
function CreditsBilling({ context, state, appKey, openIframe = null }) {
|
|
242
243
|
const onPaidPlan = !!state?.entitlement?.plan;
|
|
243
244
|
|
|
244
245
|
// Direct external link to the billing service's GET /v1/billing/portal/start,
|
|
@@ -301,7 +302,7 @@ function CreditsBilling({ context, state, appKey }) {
|
|
|
301
302
|
entitlement={state?.entitlement}
|
|
302
303
|
creditMeter={state?.credit_meter}
|
|
303
304
|
/>
|
|
304
|
-
<PlanGrid context={context} state={state} appKey={appKey} />
|
|
305
|
+
<PlanGrid context={context} state={state} appKey={appKey} openIframe={openIframe} />
|
|
305
306
|
{!hasPlans && (
|
|
306
307
|
<LoadingButton
|
|
307
308
|
href={
|
|
@@ -345,7 +346,21 @@ function LegacyBilling({ state }) {
|
|
|
345
346
|
);
|
|
346
347
|
}
|
|
347
348
|
|
|
348
|
-
|
|
349
|
+
function CompedBilling() {
|
|
350
|
+
return (
|
|
351
|
+
<Alert variant="success">
|
|
352
|
+
<Flex direction="column" gap="extra-small">
|
|
353
|
+
<Text format={{ fontWeight: "bold" }}>Free access</Text>
|
|
354
|
+
<Text>
|
|
355
|
+
Your account has been granted complimentary access as a Growth Operations partner or
|
|
356
|
+
team member. No payment method or subscription is required.
|
|
357
|
+
</Text>
|
|
358
|
+
</Flex>
|
|
359
|
+
</Alert>
|
|
360
|
+
);
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
export function BillingTab({ context, state, appKey, openIframe = null }) {
|
|
349
364
|
const mode = state?.entitlement?.mode;
|
|
350
365
|
|
|
351
366
|
return (
|
|
@@ -354,9 +369,11 @@ export function BillingTab({ context, state, appKey }) {
|
|
|
354
369
|
{mode === "legacy" ? (
|
|
355
370
|
<LegacyBilling state={state} />
|
|
356
371
|
) : mode === "credits" ? (
|
|
357
|
-
<CreditsBilling context={context} state={state} appKey={appKey} />
|
|
372
|
+
<CreditsBilling context={context} state={state} appKey={appKey} openIframe={openIframe} />
|
|
373
|
+
) : mode === "comped" ? (
|
|
374
|
+
<CompedBilling />
|
|
358
375
|
) : (
|
|
359
|
-
<TrialSubscriptionBilling context={context} state={state} appKey={appKey} />
|
|
376
|
+
<TrialSubscriptionBilling context={context} state={state} appKey={appKey} openIframe={openIframe} />
|
|
360
377
|
)}
|
|
361
378
|
</Flex>
|
|
362
379
|
);
|
package/src/billing/PlanGrid.jsx
CHANGED
|
@@ -60,6 +60,13 @@ function PlanCard({
|
|
|
60
60
|
// CTA. Cards ranked ABOVE are upgrades (the normal CTA). null/undefined => the
|
|
61
61
|
// credit first-purchase grid, where this relation doesn't apply.
|
|
62
62
|
currentOrder = null,
|
|
63
|
+
// actions.openIframeModal from the card root (threaded BillingTab → PlanGrid).
|
|
64
|
+
// When present, a talk_to_sales tier with plan.meetings_url opens the meetings
|
|
65
|
+
// scheduler in an IN-CARD modal (the Anvil "Meet with Andrew" experience).
|
|
66
|
+
// Absent (or no meetings_url) → fall back to a new-tab href. UI Extensions
|
|
67
|
+
// can't read whether the external meetings page is CSP-frameable, so the modal
|
|
68
|
+
// is best-effort; the href fallback always works.
|
|
69
|
+
openIframe = null,
|
|
63
70
|
}) {
|
|
64
71
|
// Default this card to annual when it offers annual (cheaper-per-month story);
|
|
65
72
|
// monthly-only tiers default to monthly. Both legs → show the toggle.
|
|
@@ -184,13 +191,39 @@ function PlanCard({
|
|
|
184
191
|
Talk to sales to switch
|
|
185
192
|
</Button>
|
|
186
193
|
) : plan.talk_to_sales ? (
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
+
// Talk-to-sales tier (e.g. Enterprise+): no price/checkout. If we have
|
|
195
|
+
// a meetings link AND the openIframeModal action, open the scheduler in
|
|
196
|
+
// an in-card modal (Anvil "Meet with Andrew"). Otherwise a new-tab href
|
|
197
|
+
// to the meetings link (preferred) or support page.
|
|
198
|
+
openIframe && plan.meetings_url ? (
|
|
199
|
+
<Button
|
|
200
|
+
variant="secondary"
|
|
201
|
+
onClick={() =>
|
|
202
|
+
openIframe({
|
|
203
|
+
uri: plan.meetings_url,
|
|
204
|
+
title: `Talk to sales — ${plan.name ?? plan.tier}`,
|
|
205
|
+
width: 1100,
|
|
206
|
+
height: 760,
|
|
207
|
+
})
|
|
208
|
+
}
|
|
209
|
+
>
|
|
210
|
+
Talk to sales
|
|
211
|
+
</Button>
|
|
212
|
+
) : (
|
|
213
|
+
<Button
|
|
214
|
+
href={
|
|
215
|
+
plan.meetings_url
|
|
216
|
+
? { url: plan.meetings_url, external: true }
|
|
217
|
+
: supportUrl
|
|
218
|
+
? { url: supportUrl, external: true }
|
|
219
|
+
: undefined
|
|
220
|
+
}
|
|
221
|
+
disabled={!plan.meetings_url && !supportUrl}
|
|
222
|
+
variant="secondary"
|
|
223
|
+
>
|
|
224
|
+
Talk to sales
|
|
225
|
+
</Button>
|
|
226
|
+
)
|
|
194
227
|
) : !leg ? (
|
|
195
228
|
// No price for the selected interval (e.g. annual not offered) — guide
|
|
196
229
|
// the customer to the other toggle rather than dead-ending.
|
|
@@ -232,6 +265,9 @@ export function PlanGrid({
|
|
|
232
265
|
// Trial-picker only: tier_order of the current tier, so cards below it render
|
|
233
266
|
// as disabled downgrades (Talk-to-sales). Omitted for the credit grid.
|
|
234
267
|
currentOrder = null,
|
|
268
|
+
// actions.openIframeModal (from the hosting card root) — lets a talk_to_sales
|
|
269
|
+
// tier open its meetings_url scheduler in an in-card modal. Optional.
|
|
270
|
+
openIframe = null,
|
|
235
271
|
}) {
|
|
236
272
|
const plans = plansOverride ?? state?.plans ?? [];
|
|
237
273
|
|
|
@@ -273,6 +309,7 @@ export function PlanGrid({
|
|
|
273
309
|
endpoint={endpoint}
|
|
274
310
|
ctaLabel={ctaLabel}
|
|
275
311
|
currentOrder={currentOrder}
|
|
312
|
+
openIframe={openIframe}
|
|
276
313
|
/>
|
|
277
314
|
))}
|
|
278
315
|
</AutoGrid>
|
package/src/home/HealthHero.jsx
CHANGED
|
@@ -50,6 +50,17 @@ export function HealthHero({ appName, state }) {
|
|
|
50
50
|
) : null;
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
+
if (ent.mode === "comped") {
|
|
54
|
+
return (
|
|
55
|
+
<Flex direction="column" gap="small">
|
|
56
|
+
{name && <Heading>{name}</Heading>}
|
|
57
|
+
<Alert title="Free access" variant="success">
|
|
58
|
+
<Text>Partner or team member access — no subscription required.</Text>
|
|
59
|
+
</Alert>
|
|
60
|
+
</Flex>
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
|
|
53
64
|
if (ent.mode === "credits") {
|
|
54
65
|
const remaining = ent.remaining ?? 0;
|
|
55
66
|
const depleted = ent.depleted === true || remaining <= 0;
|