Skip to content

React SDK 0.11.0

Choose a tag to compare

@pratham2609 pratham2609 released this 17 Oct 16:20
· 20 commits to main since this release
bac9d94

Breaking

  • Components no longer read Tailwind classes, host CSS or shadcn's --primary, --primary-foreground and --border variables. Pass your colours as appearance.variables instead (for example colorPrimary: "var(--primary)"). Without an appearance, components use the light look: primary #4f46e5. The billing portal's green accent (#526949) is gone; set colorPrimary or the older --nozle-portal-accent to keep it.
  • @tanstack/react-query (v5) is a required peer dependency. usePlans now runs on TanStack Query through BillingProvider's query client and keeps its return shape, plus refetch.
  • PricingTable no longer marks a plan "Custom" because its name or code contains "enterprise" or "custom". List the codes of plans sold on request in contactSalesPlans; their card shows "Custom" and a "Contact Sales" button that opens enterpriseEmail.
  • PlanCard takes plan (a catalog plan) with isCurrent, returnUrl, onSelect and the optional features. It no longer takes id, name, monthlyPrice, annualPrice, description, isAnnual or children, and the Plan type export is removed.
  • PlanComparison takes plans (catalog plans) and the optional features. A plan that lacks an entitlement shows a cross. features rows are keyed by plan code, not id.

Added

  • appearance on BillingProvider and on every component that renders UI. It takes a theme from @nozle-js/react/themes (light, dark, minimal, neobrutal, nozle or nozleDark; an array stacks them, last wins), your own variables, and per-element elements, where a string adds a class name and an object adds inline styles. Every part has a fixed nozle-<key> class, such as nozle-pricingTable or nozle-planCard__price. A component's own appearance goes on top of the provider's. Components render without Tailwind or host CSS; they read --nozle-* CSS variables, and the older --nozle-portal-* and --nozle-pricing-* names still work. Checkout passes the resolved theme to Stripe's Payment Element (Stripe's night theme on a dark background). useAppearance and the Appearance, Theme, Variables, Elements, ElementKey, UseAppearance and ElementProps types are exported.
  • PricingTable takes highlightStyle: outline (default) draws the highlighted card's border in colorHighlight; filled paints the card in colorHighlight and its text and button in colorHighlightForeground. Both variables default to the primary colours. highlightLabel sets the badge on the highlighted card (default "Most Popular"; null shows no badge).
  • Two more themes, nozle and nozleDark, give the Nozle dashboard look (flat cards, a hard ink shadow on buttons, Nunito). New variables buttonRadius and buttonBorderWidth (every button), buttonBorderColor and buttonShadow (primary buttons only), colorSecondary and colorInput (secondary buttons), and labelFont, labelTextTransform, labelLetterSpacing and fontFamilyNumbers for table headers, status labels and numbers; a theme's planCardLayout: "panel" lays plan cards out like the dashboard, with ACTIVE on the current plan. neobrutal primary buttons get a black border and offset shadow.
  • Text roles. New variables fontTitle, fontHeading, fontMetric, fontBody, fontMeta and fontAction (CSS font shorthands, written as --nozle-font-title and so on) set the type of every element, with labelFont as the label role; each defaults to a size in fontFamily (fontMetric in fontFamilyNumbers when set, in tabular figures). Every component root sets the body role, so no text takes its size, font or colour from the host page, including the PricingTable toggle, the UsageAlert dismiss button, the CheckoutButton status and error, Checkout, the billing portal and its dialogs. nozle and nozleDark set the dashboard scale (title 20/900, heading 14/900, price 24/800 in Nunito, body 13, meta 11.5, buttons 14/800); neobrutal sets bolder titles and headings.
  • Customer billing hooks built on TanStack Query: useSubscription (with past_due), useEntitlement(featureCode), useCreditBalance(creditSystemCode?), useCreditHistory() (paged, operations ready for CreditHistory), useUsage({ period }) (current period for UsageBreakdown, past periods for UsageTrend), useUpgradePreview(planCode), useInvoices({ page }), useInvoiceDownload() (resolves an invoice's PDF URL, or null while it is generated) and useBillingRefresh(). They read your backend route set as BillingProvider billingEndpoint (with billingHeaders for a CSRF token), served by createBillingHandler from @nozle-js/node, so the browser holds no secret key and sees only the signed-in customer. BillingProvider takes an optional queryClient to share your app's cache; the hooks pass their client explicitly and never replace your QueryClientProvider. Failed requests throw BillingRequestError (status, code, requestId); a 4xx is not retried.
  • CurrentPlan shows the customer's plan, status, price, scheduled change, usage against the plan's limits and a near-limit notice, and an alert when the subscription is past due. It reads the billing hooks by default; subscription, usage, details and actions can be passed instead. currentPlanMeters(entitlements, usage) returns its meter rows for your own layout.
  • PricingTable, PlanCard and PlanComparison read what each plan gives from the public catalog: entitlements, credit grants and the usage prices of every charge model except custom and dynamic. PricingTable accepts an optional features (an array aligned to the rendered plans, or an object keyed by plan code), PlanCard an optional features list and PlanComparison optional features rows. When passed, they replace the generated lines.
  • planFeatures(plan) and comparisonRows(plans) return the same lines and rows for your own layout. The CatalogEntitlement, CatalogCreditGrantRule, CatalogCharge, CatalogPrivilege and ComparisonRow types are exported, and CatalogPlan and PricingPlan declare the optional entitlements, credit_grant_rules and charges fields.
  • PricingTable and PlanComparison sort plans by base price, cheapest first (PricingTable puts contactSalesPlans last), instead of showing the catalog's newest-first order. Plans in different currencies stay grouped, and ties keep the catalog order. Pass sort to use your own order. sortPlansByPrice(plans) is exported. A features array is aligned to the sorted order.
  • CreditBalance and CreditHistory render the SDK's credit balance and credit operations (CreditBalanceData, CreditOperationData), each with loading, error and empty states; CreditHistory has a load-more button for the SDK's next_cursor. usageItems(entitlements, results) builds UsageDashboard rows from a plan's metered entitlements and can() results. UsageDashboard takes error and emptyMessage, and UsageMeter and UsageDashboard accept a null or missing limit and show Unlimited.
  • UsageBreakdown (a table of each feature's units and amount for one period, with the total) and UsageTrend (a bar chart of the amount, or the units of one featureCode, per period) render the usage your backend reads from Core's current_usage and past_usage (CustomerUsageData, ChargeUsageData). Both have loading, error and empty states and no chart library.
  • PricingTable, PlanComparison, CurrentPlan, Checkout, UpgradeModal and BillingPortal show "Powered by" and the Nozle logo when the merchant's Nozle plan keeps the branding (meta.nozle_branding in the publishable-key catalog, nozleBranding in the portal). Only the outermost of nested components shows it. useNozleBranding() and PoweredByNozle are exported for your own UI. The portal's plain "Powered by Nozle" footer is replaced. PricingTable and usePlans share one cached catalog request.
  • Changing plan in PlanChangeControl (and the billing portal) lists the plans as choices with price, upgrade or downgrade, and, inside a BillingProvider, each plan's description and features from the catalog; the confirmation step has a Back button. UpgradeModal takes onBack. The portal subscription card puts View usage, Change plan and Cancel subscription in one action row.

Changed

  • PricingTable gives plans priced above the current plan the primary button and the current and cheaper plans the plain one (without a current plan, only the highlighted plan gets the primary button).
  • Tables (CreditHistory, UsageBreakdown, PlanComparison and the billing portal's usage and invoice tables) follow the Nozle dashboard table: a bordered frame, a tinted header band, 20px cell padding, one-line cells and right-aligned numbers in tabular figures; each theme styles the header labels its own way. The billing portal's invoice search is a single search field with an icon.
  • UsageDashboard has the same card frame as the other data components. A UsageMeter value is in the text colour below 80% and turns to the warning colour at 80% and the danger colour at 95%, instead of always taking the bar colour.
  • Muted text follows colorForeground. When colorMutedForeground is not set it is colorForeground mixed 62% into colorCard instead of a fixed #6b7280; the light and dark themes use the same mix. Error and success text use contrast-adjusted colours like warning text already did. Sizes are now the same for the same kind of text across components, so the default look changes slightly: plan names are 16px, prices and balances 28px, buttons 14px, badges and status pills use the label role. The panel plan card no longer hard-codes the dashboard sizes; the themes supply them.

Deprecated

  • nozlePreset (@nozle-js/react/styles/preset) has no effect on the components, which no longer use Tailwind. It is kept so existing imports still build. Theme the components with appearance instead.

Fixed

  • The built package keeps "use client" on the main entry, so a Next.js server component can render the components without a wrapper; before, it failed with "createContext only works in Client Components". @nozle-js/react/themes stays importable from server components.
  • useUsage() is typed per period: CustomerUsageData | null for the current period and CustomerUsageData[] with { period: "past" }, so its data passes to UsageBreakdown and UsageTrend without a cast. PricingPlan.description accepts null, so usePlans().plans passes to PricingTable, PlanCard and PlanComparison as is. PoweredByNozle used on its own takes the theme's colours.
  • Component buttons (UpgradePrompt, PlanCard, PricingTable and its toggle, UsageAlert dismiss, PaymentMethodDisplay) are type="button", so they no longer submit a form they sit inside.
  • PricingTable shows the real billing interval (/quarter, /week, /6 months) instead of /month for every plan that is not yearly.
  • PlanCard prints the plan's own currency instead of $ for every plan.
  • The annual toggle no longer shows a hard-coded "Save 20%".