@metrifox/react-sdk 0.0.20-beta.1 → 0.0.20-beta.10
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 +185 -226
- package/dist/index.cjs +38 -55
- package/dist/index.d.ts +95 -48
- package/dist/index.js +41 -58
- package/dist/styles.css +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -4,6 +4,21 @@ A fully-configurable **React SDK** providing ready-to-use widgets for SaaS and b
|
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
+
## ⚠️ Version notice – breaking changes
|
|
8
|
+
|
|
9
|
+
**If you are upgrading from an earlier version of the SDK, please read this.**
|
|
10
|
+
|
|
11
|
+
This release introduces a **new theme structure** for both **Customer Portal** and **Pricing Table**. The theme API has been reorganized and is **not backward compatible** with previous versions.
|
|
12
|
+
|
|
13
|
+
- **Theme is now a single object** passed via `metrifoxInit({ theme })` with two keys: `customerPortal` and `pricingTable`. The previous top-level `pricingTableTheme` option is **deprecated**; use `theme.pricingTable` instead.
|
|
14
|
+
- **Customer Portal theme** uses a new grouped shape: `general`, `tabs`, `sections`, `buttons`, `lineItems`, `tables`, `modals`, and `plans`. Property names and nesting have changed from older versions.
|
|
15
|
+
- **Pricing Table theme** now strictly follows the same nested structure as Customer Portal: all plan-related keys must be under `plans` (e.g. `plans.planCards`, `plans.planToggle`). Top-level plan keys are no longer supported.
|
|
16
|
+
- **Both widgets** accept an optional `theme` prop per instance to override or extend the global theme from `metrifoxInit`.
|
|
17
|
+
|
|
18
|
+
If you were using custom themes before, you will need to **migrate your theme objects** to the new structure. Omit any keys you don't need; the SDK merges your values with defaults. See the [Styling](#styling) section below for the full theme shapes and examples.
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
7
22
|
## Installation
|
|
8
23
|
|
|
9
24
|
```bash
|
|
@@ -59,12 +74,13 @@ export default function MyPortalPage() {
|
|
|
59
74
|
{ key: "plan", component: MyCustomPlan, props: { foo: "bar" } },
|
|
60
75
|
{ key: "billingHistory", hidden: true },
|
|
61
76
|
]}
|
|
77
|
+
theme={{ general: { linkColor: "#2563eb" } }}
|
|
62
78
|
/>
|
|
63
79
|
)
|
|
64
80
|
}
|
|
65
81
|
```
|
|
66
82
|
|
|
67
|
-
|
|
83
|
+
Optional **`theme`** prop: pass a `CustomerPortalTheme` object to override or extend the global theme from `metrifoxInit` for this instance only.
|
|
68
84
|
|
|
69
85
|
#### Section Configuration
|
|
70
86
|
|
|
@@ -115,7 +131,13 @@ Displays subscription plans and one-time purchases in a configurable pricing tab
|
|
|
115
131
|
import { PricingTable } from "@metrifox/react-sdk"
|
|
116
132
|
|
|
117
133
|
export default function PricingPage() {
|
|
118
|
-
return
|
|
134
|
+
return (
|
|
135
|
+
<PricingTable
|
|
136
|
+
checkoutUsername="your-checkout-username"
|
|
137
|
+
productKey="your-product-key"
|
|
138
|
+
theme={{ plans: { planCards: { background: "#ffffff" } } }}
|
|
139
|
+
/>
|
|
140
|
+
)
|
|
119
141
|
}
|
|
120
142
|
```
|
|
121
143
|
|
|
@@ -125,19 +147,20 @@ export default function PricingPage() {
|
|
|
125
147
|
|
|
126
148
|
The props control how the pricing table is configured.
|
|
127
149
|
|
|
128
|
-
| Property | Type
|
|
129
|
-
| --------------------- |
|
|
130
|
-
| `checkoutUsername` | `string`
|
|
131
|
-
| `productKey` | `string`
|
|
132
|
-
| `plansOnly` | `boolean`
|
|
133
|
-
| `singlePurchasesOnly` | `boolean`
|
|
134
|
-
| `showTabHeader` | `boolean`
|
|
150
|
+
| Property | Type | Required | Default | Description |
|
|
151
|
+
| --------------------- | ------------------ | -------- | ------- | -------------------------------------------------------------------------------- |
|
|
152
|
+
| `checkoutUsername` | `string` | Yes | — | Unique username used for checkout. This can be found in **Settings → Checkout**. |
|
|
153
|
+
| `productKey` | `string` | Yes | — | Unique product identifier. This can be found on the product page. |
|
|
154
|
+
| `plansOnly` | `boolean` | No | `false` | Controls whether only subscription plans are rendered. |
|
|
155
|
+
| `singlePurchasesOnly` | `boolean` | No | `false` | Controls whether only single purchases are rendered. |
|
|
156
|
+
| `showTabHeader` | `boolean` | No | `true` | Controls whether the tab header for switching between offerings is rendered. |
|
|
157
|
+
| `theme` | `PricingTableTheme`| No | — | Optional theme override for this instance (merged with global theme from `metrifoxInit`). |
|
|
135
158
|
|
|
136
159
|
> **Note:** If both `plansOnly` and `singlePurchasesOnly` are `false` or undefined, both plans and single purchases are displayed.
|
|
137
160
|
|
|
138
161
|
## Styling
|
|
139
162
|
|
|
140
|
-
Import the SDK
|
|
163
|
+
Import the SDK's global styles into your app entry (e.g., `src/index.tsx` or `_app.tsx`):
|
|
141
164
|
|
|
142
165
|
```tsx
|
|
143
166
|
import "@metrifox/react-sdk/dist/styles.css"
|
|
@@ -145,271 +168,207 @@ import "@metrifox/react-sdk/dist/styles.css"
|
|
|
145
168
|
|
|
146
169
|
> This is required for proper styling of all widgets.
|
|
147
170
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
The SDK accepts an optional `theme` object during initialization. This theme is applied to Widgets and UI elements within them to match your brand styles.
|
|
171
|
+
### Theme configuration (new structure)
|
|
151
172
|
|
|
152
|
-
Any
|
|
173
|
+
Theming is driven by a single `theme` object passed to `metrifoxInit`. It has two top-level keys: `customerPortal` and `pricingTable`. Any value you omit falls back to the SDK default. You can also pass an optional `theme` prop to `<CustomerPortal />` or `<PricingTable />` to override or extend the global theme for that instance.
|
|
153
174
|
|
|
154
175
|
```ts
|
|
176
|
+
// Passed to metrifoxInit({ theme })
|
|
155
177
|
theme?: {
|
|
156
178
|
customerPortal?: CustomerPortalTheme
|
|
157
179
|
pricingTable?: PricingTableTheme
|
|
158
180
|
}
|
|
159
181
|
```
|
|
160
182
|
|
|
161
|
-
|
|
162
|
-
// Customer portal theme configuration
|
|
163
|
-
customerPortalTheme?: {
|
|
164
|
-
tabs?: {
|
|
165
|
-
background?: string
|
|
166
|
-
borderColor?: string
|
|
167
|
-
activeBackground?: string
|
|
168
|
-
activeTextColor?: string
|
|
169
|
-
inactiveTextColor?: string
|
|
170
|
-
}
|
|
183
|
+
> **Deprecated:** The previous root-level `pricingTableTheme` option is no longer supported. Use `theme.pricingTable` instead.
|
|
171
184
|
|
|
172
|
-
|
|
173
|
-
background?: string
|
|
174
|
-
titleTextColor?: string
|
|
175
|
-
contentBackground?: string
|
|
176
|
-
iconBackground?: string
|
|
177
|
-
iconColor?: string
|
|
178
|
-
emptyTextColor?: string
|
|
179
|
-
}
|
|
185
|
+
---
|
|
180
186
|
|
|
181
|
-
|
|
182
|
-
titleBackground?: string
|
|
183
|
-
contentBackground?: string
|
|
184
|
-
titleColor?: string
|
|
185
|
-
details?: {
|
|
186
|
-
labelColor?: string
|
|
187
|
-
valueColor?: string
|
|
188
|
-
}
|
|
189
|
-
}
|
|
187
|
+
### Customer Portal theme (`CustomerPortalTheme`)
|
|
190
188
|
|
|
191
|
-
|
|
192
|
-
items?: {
|
|
193
|
-
background?: string
|
|
194
|
-
borderColor?: string
|
|
195
|
-
textColor?: string
|
|
196
|
-
}
|
|
197
|
-
}
|
|
189
|
+
All properties are optional. The shape is grouped by area of the UI:
|
|
198
190
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
191
|
+
| Group | Description |
|
|
192
|
+
| ----- | ----------- |
|
|
193
|
+
| `general` | Page-level: link color, background, border radius, font family, container padding |
|
|
194
|
+
| `tabs` | Tab bar (e.g. Wallet balance tabs): background, border, active/inactive states |
|
|
195
|
+
| `sections` | Section cards: background, padding, borders, content/summaryBalance sub-styles, header/label/value typography, usage bars, empty text |
|
|
196
|
+
| `buttons` | Primary and secondary buttons: background, border (color/width/radius), typography |
|
|
197
|
+
| `lineItems` | Subscription line items: parentRow/childRow background, border, typography (label/quantity) |
|
|
198
|
+
| `tables` | Tables (e.g. billing history): header/row colors, border, cell padding, expand icon, typography |
|
|
199
|
+
| `modals` | Modal overlay, background, border, close button; header/title/description typography; footer primary/secondary buttons |
|
|
200
|
+
| `plans` | Plan cards when shown in portal: currentPlanCard, planCards (border as `{ color, width, radius }`), planFeatures, planButton, planToggle, planTags |
|
|
203
201
|
|
|
204
|
-
|
|
205
|
-
background?: string
|
|
206
|
-
textColor?: string
|
|
207
|
-
}
|
|
202
|
+
**Example – minimal override:**
|
|
208
203
|
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
204
|
+
```ts
|
|
205
|
+
customerPortal: {
|
|
206
|
+
general: { linkColor: "#2563eb", backgroundColor: "#ffffff" },
|
|
207
|
+
tabs: {
|
|
208
|
+
tabBackground: "#ffffff",
|
|
209
|
+
tabBorderColor: "#e5e7eb",
|
|
210
|
+
activeTabBackground: "#2563eb",
|
|
211
|
+
activeTabTextColor: "#ffffff",
|
|
212
|
+
inactiveTabTextColor: "#6b7280",
|
|
213
|
+
},
|
|
214
|
+
sections: {
|
|
215
|
+
background: "#ffffff",
|
|
216
|
+
content: { background: "#f4f4f5", borderRadius: "8px" },
|
|
217
|
+
header: { fontSize: "16px", fontWeight: "600", color: "#52525b" },
|
|
218
|
+
label: { fontSize: "13px", color: "#71717a" },
|
|
219
|
+
value: { fontSize: "16px", color: "#52525b" },
|
|
220
|
+
},
|
|
221
|
+
buttons: {
|
|
222
|
+
primary: { backgroundColor: "#2563eb", border: { radius: "8px" }, typography: { color: "#ffffff" } },
|
|
223
|
+
secondary: { backgroundColor: "#e4e4e7", typography: { color: "#3f3f46" } },
|
|
224
|
+
},
|
|
225
|
+
plans: {
|
|
226
|
+
planCards: {
|
|
227
|
+
background: "#ffffff",
|
|
228
|
+
border: { color: "#e5e7eb", width: "1px", radius: "8px" },
|
|
229
|
+
header: { background: "#e5e7eb", textColor: "#111827" },
|
|
230
|
+
description: { textColor: "#6b7280", textButtonColor: "#2563eb" },
|
|
231
|
+
price: { amountColor: "#111827", primaryTextColor: "#6b7280", secondaryTextColor: "#9ca3af" },
|
|
232
|
+
},
|
|
233
|
+
planButton: { background: "#2563eb", textColor: "#ffffff" },
|
|
234
|
+
planToggle: { background: "#e5e7eb", activeBackground: "#1f2937", activeText: "#ffffff", inactiveText: "#6b7280" },
|
|
235
|
+
},
|
|
236
|
+
}
|
|
237
|
+
```
|
|
218
238
|
|
|
219
|
-
|
|
239
|
+
---
|
|
220
240
|
|
|
221
|
-
|
|
222
|
-
card?: {
|
|
223
|
-
background?: string
|
|
224
|
-
borderColor?: string
|
|
225
|
-
descriptionColor?: string
|
|
241
|
+
### Font customization
|
|
226
242
|
|
|
227
|
-
|
|
228
|
-
background?: string
|
|
229
|
-
textColor?: string
|
|
230
|
-
}
|
|
243
|
+
The SDK accepts **any font-family string** in your theme. The SDK applies it via CSS, but **your app must load the font** (Google Fonts, @font-face, etc.) before the SDK renders.
|
|
231
244
|
|
|
232
|
-
|
|
233
|
-
textColor?: string
|
|
234
|
-
textButtonColor?: string
|
|
235
|
-
}
|
|
245
|
+
**How it works:**
|
|
236
246
|
|
|
237
|
-
|
|
238
|
-
amountColor?: string
|
|
239
|
-
primaryTextColor?: string
|
|
240
|
-
secondaryTextColor?: string
|
|
241
|
-
textButtonColor?: string
|
|
242
|
-
background?: string
|
|
243
|
-
borderColor?: string
|
|
244
|
-
}
|
|
245
|
-
}
|
|
247
|
+
1. **Load the font in your app** (HTML, CSS, or framework-specific):
|
|
246
248
|
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
secondaryTextColor?: string
|
|
252
|
-
textButtonColor?: string
|
|
253
|
-
}
|
|
249
|
+
```html
|
|
250
|
+
<!-- Option A: Google Fonts in your HTML <head> -->
|
|
251
|
+
<link href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;500;600&display=swap" rel="stylesheet">
|
|
252
|
+
```
|
|
254
253
|
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
254
|
+
```css
|
|
255
|
+
/* Option B: @font-face in your global CSS */
|
|
256
|
+
@font-face {
|
|
257
|
+
font-family: 'MyCustomFont';
|
|
258
|
+
src: url('/fonts/custom.woff2') format('woff2');
|
|
259
|
+
}
|
|
260
|
+
```
|
|
259
261
|
|
|
260
|
-
|
|
261
|
-
background?: string
|
|
262
|
-
activeBackground?: string
|
|
263
|
-
activeText?: string
|
|
264
|
-
inactiveText?: string
|
|
265
|
-
}
|
|
262
|
+
2. **Pass the font-family to the SDK theme:**
|
|
266
263
|
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
264
|
+
```tsx
|
|
265
|
+
metrifoxInit({
|
|
266
|
+
theme: {
|
|
267
|
+
customerPortal: {
|
|
268
|
+
general: {
|
|
269
|
+
// Any font-family string works
|
|
270
|
+
fontFamily: '"Space Grotesk", "Inter", sans-serif'
|
|
271
|
+
// or: 'MyCustomFont, sans-serif'
|
|
272
|
+
// or: 'system-ui, -apple-system, sans-serif'
|
|
271
273
|
}
|
|
272
|
-
gradientColor?: string
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
freeTrialTag?: {
|
|
276
|
-
background?: string
|
|
277
|
-
textColor?: string
|
|
278
274
|
}
|
|
279
275
|
}
|
|
280
|
-
}
|
|
276
|
+
})
|
|
281
277
|
```
|
|
282
278
|
|
|
283
|
-
|
|
284
|
-
// Pricing table theme configuration
|
|
285
|
-
pricingTableTheme?: {
|
|
286
|
-
card?: {
|
|
287
|
-
background?: string
|
|
288
|
-
borderColor?: string
|
|
289
|
-
descriptionColor?: string
|
|
290
|
-
|
|
291
|
-
header?: {
|
|
292
|
-
background?: string
|
|
293
|
-
textColor?: string
|
|
294
|
-
}
|
|
279
|
+
If no `fontFamily` is provided, the SDK inherits the font from the host page. This means the SDK works with whatever font your app already uses — no extra configuration needed.
|
|
295
280
|
|
|
296
|
-
|
|
297
|
-
textColor?: string
|
|
298
|
-
textButtonColor?: string
|
|
299
|
-
}
|
|
281
|
+
> **Important:** When using Google Fonts or custom fonts, load them in your app **before** the SDK initializes to prevent flash of unstyled text (FOUT).
|
|
300
282
|
|
|
301
|
-
|
|
302
|
-
amountColor?: string
|
|
303
|
-
primaryTextColor?: string
|
|
304
|
-
secondaryTextColor?: string
|
|
305
|
-
textButtonColor?: string
|
|
306
|
-
background?: string
|
|
307
|
-
borderColor?: string
|
|
308
|
-
}
|
|
309
|
-
}
|
|
283
|
+
---
|
|
310
284
|
|
|
311
|
-
|
|
312
|
-
background?: string
|
|
313
|
-
textColor?: string
|
|
314
|
-
secondaryBackground?: string
|
|
315
|
-
secondaryTextColor?: string
|
|
316
|
-
textButtonColor?: string
|
|
317
|
-
}
|
|
285
|
+
### Pricing Table theme (`PricingTableTheme`)
|
|
318
286
|
|
|
319
|
-
|
|
320
|
-
textColor?: string
|
|
321
|
-
iconColor?: string
|
|
322
|
-
}
|
|
287
|
+
The Pricing Table theme follows the same nested structure as Customer Portal. All plan-related keys must be nested under `plans`.
|
|
323
288
|
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
289
|
+
| Key | Description |
|
|
290
|
+
| --- | ----------- |
|
|
291
|
+
| `plans` | Container for all plan-related styling |
|
|
292
|
+
| `plans.currentPlanCard` | Current-plan highlight: header (background, textColor), gradientColor, description, borderRadius |
|
|
293
|
+
| `plans.planCards` | Card style: background, border (`{ color, width, radius }`), header, description (textColor, textButtonColor), price (amountColor, primaryTextColor, secondaryTextColor, textButtonColor, background, borderColor) |
|
|
294
|
+
| `plans.planFeatures` | Feature list: textColor, iconColor |
|
|
295
|
+
| `plans.planButton` | CTA button: background, textColor; optional secondaryBackground, secondaryTextColor, textButtonColor |
|
|
296
|
+
| `plans.planToggle` | Monthly/Yearly toggle: background, activeBackground, activeText, inactiveText |
|
|
297
|
+
| `plans.planTags` | Tags (e.g. free trial): freeTrialBackground, freeTrialText |
|
|
298
|
+
| `tabs` | Tabs (e.g. Plans vs Single purchases): inactiveText, activeText, indicator, borderColor |
|
|
299
|
+
| `checkoutBar` | Bottom checkout bar: background, borderColor, textColor, buttonBackground, buttonTextColor |
|
|
330
300
|
|
|
331
|
-
|
|
332
|
-
background?: string
|
|
333
|
-
activeBackground?: string
|
|
334
|
-
activeText?: string
|
|
335
|
-
inactiveText?: string
|
|
336
|
-
}
|
|
301
|
+
**Example – minimal override:**
|
|
337
302
|
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
textColor
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
303
|
+
```ts
|
|
304
|
+
pricingTable: {
|
|
305
|
+
plans: {
|
|
306
|
+
planCards: {
|
|
307
|
+
background: "#ffffff",
|
|
308
|
+
border: { color: "#e5e7eb", width: "1px", radius: "8px" },
|
|
309
|
+
header: { background: "#e5e7eb", textColor: "#111827" },
|
|
310
|
+
description: { textColor: "#6b7280", textButtonColor: "#2563eb" },
|
|
311
|
+
price: { amountColor: "#111827", primaryTextColor: "#6b7280", secondaryTextColor: "#9ca3af" },
|
|
312
|
+
},
|
|
313
|
+
planButton: { background: "#2563eb", textColor: "#ffffff" },
|
|
314
|
+
planToggle: { background: "#e5e7eb", activeBackground: "#1f2937", activeText: "#ffffff", inactiveText: "#6b7280" },
|
|
315
|
+
},
|
|
316
|
+
tabs: { activeText: "#2563eb", indicator: "#2563eb", borderColor: "#9ca3af" },
|
|
317
|
+
checkoutBar: {
|
|
318
|
+
background: "#f9fafb",
|
|
319
|
+
borderColor: "#e5e7eb",
|
|
320
|
+
textColor: "#3f3f46",
|
|
321
|
+
buttonBackground: "#2563eb",
|
|
322
|
+
buttonTextColor: "#ffffff",
|
|
323
|
+
},
|
|
358
324
|
}
|
|
359
325
|
```
|
|
360
326
|
|
|
361
|
-
|
|
327
|
+
When the Pricing Table is embedded inside the Customer Portal, it automatically uses `theme.customerPortal.plans` for plan styling so both widgets stay consistent.
|
|
328
|
+
|
|
329
|
+
---
|
|
330
|
+
|
|
331
|
+
### Full example
|
|
362
332
|
|
|
363
333
|
```tsx
|
|
364
334
|
import { metrifoxInit } from "@metrifox/react-sdk"
|
|
365
335
|
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
336
|
+
metrifoxInit({
|
|
337
|
+
clientKey: "your-client-key",
|
|
338
|
+
theme: {
|
|
339
|
+
customerPortal: {
|
|
340
|
+
general: { linkColor: "#2563eb", backgroundColor: "#ffffff" },
|
|
341
|
+
tabs: {
|
|
342
|
+
tabBackground: "#ffffff",
|
|
343
|
+
activeTabBackground: "#2563eb",
|
|
344
|
+
activeTabTextColor: "#ffffff",
|
|
345
|
+
inactiveTabTextColor: "#6b7280",
|
|
346
|
+
},
|
|
347
|
+
sections: {
|
|
348
|
+
background: "#ffffff",
|
|
349
|
+
content: { background: "#f4f4f5", borderRadius: "8px" },
|
|
350
|
+
},
|
|
351
|
+
buttons: {
|
|
352
|
+
primary: { backgroundColor: "#2563eb", typography: { color: "#ffffff" } },
|
|
373
353
|
},
|
|
374
354
|
},
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
const customerPortalTheme = {
|
|
385
|
-
tabs: {
|
|
386
|
-
background: "#111827",
|
|
387
|
-
borderColor: "#243044",
|
|
388
|
-
},
|
|
389
|
-
|
|
390
|
-
section: {
|
|
391
|
-
background: "#020617",
|
|
392
|
-
},
|
|
393
|
-
|
|
394
|
-
card: {
|
|
395
|
-
titleColor: "#F9FAFB",
|
|
396
|
-
details: {
|
|
397
|
-
labelColor: "#CBD5E1",
|
|
398
|
-
valueColor: "#FFFFFF",
|
|
355
|
+
pricingTable: {
|
|
356
|
+
plans: {
|
|
357
|
+
planCards: { background: "#ffffff", border: { color: "#e5e7eb", radius: "8px" } },
|
|
358
|
+
planButton: { background: "#2563eb", textColor: "#ffffff" },
|
|
359
|
+
},
|
|
360
|
+
tabs: { activeText: "#2563eb", indicator: "#2563eb" },
|
|
361
|
+
checkoutBar: { buttonBackground: "#2563eb", buttonTextColor: "#ffffff" },
|
|
399
362
|
},
|
|
400
363
|
},
|
|
401
|
-
}
|
|
364
|
+
})
|
|
365
|
+
```
|
|
402
366
|
|
|
403
|
-
|
|
404
|
-
customerPortal: customerPortalTheme,
|
|
405
|
-
pricingTableTheme: pricingTableTheme,
|
|
406
|
-
}
|
|
367
|
+
Per-widget overrides (optional):
|
|
407
368
|
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
pricingTableTheme, // deprecated - Moved to `theme.pricingTable`
|
|
412
|
-
})
|
|
369
|
+
```tsx
|
|
370
|
+
<CustomerPortal customerKey="..." theme={{ general: { linkColor: "#1d4ed8" } }} />
|
|
371
|
+
<PricingTable checkoutUsername="..." productKey="..." theme={{ plans: { planCards: { background: "#f8fafc" } } }} />
|
|
413
372
|
```
|
|
414
373
|
|
|
415
374
|
---
|