npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@metrifox/angular-sdk

v2.0.0

Published

Angular SDK for Metrifox - SaaS billing, customer portals, and pricing tables

Readme

MetriFox Angular SDK

A fully-configurable Angular SDK providing ready-to-use components for SaaS and billing platforms including customer portals, pricing tables, and more.


⚠️ Version notice – breaking changes (v2.0.0+)

If you are upgrading from a release before v2.0.0, read this.

From @metrifox/angular-sdk v2.0.0 onward, both Customer Portal and Pricing Table use a new theme structure. The theme API is not backward compatible with pre-2.0.0 versions.

  • Theme is now a single object passed via MetrifoxService.initialize({ theme }) with two keys: customerPortal and pricingTable. The previous top-level pricingTableTheme option is removed on v2.0.0+; use theme.pricingTable instead.
  • 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.
  • 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.
  • Both components accept an optional theme input per instance to override or extend the global theme from MetrifoxService.initialize.

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 section below for the full theme shapes and examples.


Installation

# using npm
npm install @metrifox/angular-sdk

# or pnpm
pnpm add @metrifox/angular-sdk

# or yarn
yarn add @metrifox/angular-sdk

Setup

1. Provide the SDK

Register the SDK providers in your app config:

// app.config.ts (Standalone)
import { ApplicationConfig } from "@angular/core";
import { provideMetrifox } from "@metrifox/angular-sdk";

export const appConfig: ApplicationConfig = {
  providers: [
    provideMetrifox(), // provides HttpClient + MetrifoxService
  ],
};

2. Initialize the SDK

Before using any components, initialize the SDK once with your Client key:

import { MetrifoxService } from "@metrifox/angular-sdk";

MetrifoxService.initialize({
  clientKey: "your-metrifox-client-key",
});

3. Import Styles

Add the SDK styles to your angular.json:

{
  "styles": ["src/styles.css", "node_modules/@metrifox/angular-sdk/styles.css"]
}

Or import in your global styles.css:

@import "@metrifox/angular-sdk/styles.css";

Compatible with Angular 17, 18, and 19. All components are standalone (no NgModule required).


Widgets

CustomerPortal

Displays a customizable customer dashboard with plans, subscriptions, billing, credits, and more.

import { Component } from "@angular/core";
import { CustomerPortalComponent, SectionConfig } from "@metrifox/angular-sdk";

@Component({
  selector: "app-billing",
  standalone: true,
  imports: [CustomerPortalComponent],
  template: `
    <metrifox-customer-portal
      [customerKey]="'your-customer-key'"
      [sectionsConfig]="sections"
    />
  `,
})
export class BillingComponent {
  sections: SectionConfig[] = [
    { key: "subscription" },
    { key: "plan" },
    { key: "billingHistory", hidden: true },
  ];
}

Optional theme input: pass a CustomerPortalTheme object to override or extend the global theme from MetrifoxService.initialize for this instance only.

Section Configuration

The sectionsConfig input controls what appears in the portal.

| Property | Type | Description | | ----------- | ----------------- | --------------------------------------------------- | | key | SectionKey | Unique key of the section (see list below) | | hidden | boolean | Hide this section when true | | component | Type<any> | Replace the default section with your own component | | props | Record<string, unknown> | Extra props passed to the custom or default section |

Built-in Section Keys

| Key | Description | | ------------------ | ----------------------------- | | upcomingInvoice | Displays next invoice details | | subscription | Active subscription overview | | creditBalance | Shows user wallet balance | | entitlementUsage | Displays resource usage | | paymentOverview | Payment summary and methods | | billingHistory | List of past transactions | | plan | Current plan details |

Section Anchors

Each portal section renders inside a <section id="..."> wrapper so you can link directly to segments of a customer portal view. The default anchor IDs are:

| Anchor ID | Section Key | | -------------------- | ------------------ | | #upcoming-invoice | upcomingInvoice | | #subscription | subscription | | #credit-balance | creditBalance | | #entitlement-usage | entitlementUsage | | #payment-overview | paymentOverview | | #billing-history | billingHistory | | #plan | plan |

Use these anchors when embedding the SDK or sharing deep links (e.g., https://app.example.com/portal#billing-history).


Pricing Table

Displays subscription plans and one-time purchases in a configurable pricing table component.

import { Component } from "@angular/core";
import { PricingTableComponent } from "@metrifox/angular-sdk";

@Component({
  selector: "app-pricing",
  standalone: true,
  imports: [PricingTableComponent],
  template: `
    <metrifox-pricing-table
      [checkoutUsername]="'your-checkout-username'"
      [productKey]="'your-product-key'"
    />
  `,
})
export class PricingComponent {}

Props

The inputs control how the pricing table is configured.

| Property | Type | Required | Default | Description | | --------------------- | ------------------ | -------- | ------- | -------------------------------------------------------------------------------- | | checkoutUsername | string | Yes | — | Unique username used for checkout. This can be found in Settings → Checkout. | | productKey | string | Yes | — | Unique product identifier. This can be found on the product page. | | plansOnly | boolean | No | false | Controls whether only subscription plans are rendered. | | singlePurchasesOnly | boolean | No | false | Controls whether only single purchases are rendered. | | showTabHeader | boolean | No | true | Controls whether the tab header for switching between offerings is rendered. | | theme | PricingTableTheme| No | — | Optional theme override for this instance (merged with global theme from MetrifoxService.initialize). |

Note: If both plansOnly and singlePurchasesOnly are false or undefined, both plans and single purchases are displayed.

Styling

Import the SDK's global styles (see Setup step 3).

This is required for proper styling of all components.

Theme configuration (new structure)

Theming is driven by a single theme object passed to MetrifoxService.initialize. 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 input to <metrifox-customer-portal> or <metrifox-pricing-table> to override or extend the global theme for that instance.

// Passed to MetrifoxService.initialize({ theme })
theme?: {
  customerPortal?: CustomerPortalTheme
  pricingTable?: PricingTableTheme
}

Removed on v2.0.0+: The previous root-level pricingTableTheme option is not supported. Use theme.pricingTable instead.


Customer Portal theme (CustomerPortalTheme)

All properties are optional. The shape is grouped by area of the UI:

| Group | Description | | ----- | ----------- | | general | Page-level: link color, background, border radius, font family, container padding | | tabs | Tab bar (e.g. Wallet balance tabs): background, border, active/inactive states | | sections | Section cards: background, padding, borders, content/summaryBalance sub-styles, header/label/value typography, usage bars, empty text | | buttons | Primary and secondary buttons: background, border (color/width/radius), typography | | lineItems | Subscription line items: parentRow/childRow background, border, typography (label/quantity) | | tables | Tables (e.g. billing history): header/row colors, border, cell padding, expand icon, typography | | modals | Modal overlay, background, border, close button; header/title/description typography; footer primary/secondary buttons | | plans | Plan cards when shown in portal: currentPlanCard, planCards (border as { color, width, radius }), planFeatures, planButton, planToggle, planTags |

Example – minimal override:

customerPortal: {
  general: { linkColor: "#2563eb", backgroundColor: "#ffffff" },
  tabs: {
    tabBackground: "#ffffff",
    tabBorderColor: "#e5e7eb",
    activeTabBackground: "#2563eb",
    activeTabTextColor: "#ffffff",
    inactiveTabTextColor: "#6b7280",
  },
  sections: {
    background: "#ffffff",
    content: { background: "#f4f4f5", borderRadius: "8px" },
    header: { fontSize: "16px", fontWeight: "600", color: "#52525b" },
    label: { fontSize: "13px", color: "#71717a" },
    value: { fontSize: "16px", color: "#52525b" },
  },
  buttons: {
    primary: { backgroundColor: "#2563eb", border: { radius: "8px" }, typography: { color: "#ffffff" } },
    secondary: { backgroundColor: "#e4e4e7", typography: { color: "#3f3f46" } },
  },
  plans: {
    planCards: {
      background: "#ffffff",
      border: { color: "#e5e7eb", width: "1px", radius: "8px" },
      header: { background: "#e5e7eb", textColor: "#111827" },
      description: { textColor: "#6b7280", textButtonColor: "#2563eb" },
      price: { amountColor: "#111827", primaryTextColor: "#6b7280", secondaryTextColor: "#9ca3af" },
    },
    planButton: { background: "#2563eb", textColor: "#ffffff" },
    planToggle: { background: "#e5e7eb", activeBackground: "#1f2937", activeText: "#ffffff", inactiveText: "#6b7280" },
  },
}

Font customization

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.

How it works:

  1. Load the font in your app (HTML, CSS, or framework-specific):
<!-- Option A: Google Fonts in your index.html <head> -->
<link href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;500;600&display=swap" rel="stylesheet">
/* Option B: @font-face in your global CSS */
@font-face {
  font-family: 'MyCustomFont';
  src: url('/fonts/custom.woff2') format('woff2');
}
  1. Pass the font-family to the SDK theme:
MetrifoxService.initialize({
  clientKey: "your-client-key",
  theme: {
    customerPortal: {
      general: {
        // Any font-family string works
        fontFamily: '"Space Grotesk", "Inter", sans-serif'
        // or: 'MyCustomFont, sans-serif'
        // or: 'system-ui, -apple-system, sans-serif'
      }
    }
  }
});

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.

Important: When using Google Fonts or custom fonts, load them in your app before the SDK initializes to prevent flash of unstyled text (FOUT).


Pricing Table theme (PricingTableTheme)

The Pricing Table theme follows the same nested structure as Customer Portal. All plan-related keys must be nested under plans.

| Key | Description | | --- | ----------- | | plans | Container for all plan-related styling | | plans.currentPlanCard | Current-plan highlight: header (background, textColor), gradientColor, description, borderRadius | | plans.planCards | Card style: background, border ({ color, width, radius }), header, description (textColor, textButtonColor), price (amountColor, primaryTextColor, secondaryTextColor, textButtonColor, background, borderColor) | | plans.planFeatures | Feature list: textColor, iconColor | | plans.planButton | CTA button: background, textColor; optional secondaryBackground, secondaryTextColor, textButtonColor | | plans.planToggle | Monthly/Yearly toggle: background, activeBackground, activeText, inactiveText | | plans.planTags | Tags (e.g. free trial): freeTrialBackground, freeTrialText | | tabs | Tabs (e.g. Plans vs Single purchases): inactiveText, activeText, indicator, borderColor | | checkoutBar | Bottom checkout bar: background, borderColor, textColor, buttonBackground, buttonTextColor |

Example – minimal override:

pricingTable: {
  plans: {
    planCards: {
      background: "#ffffff",
      border: { color: "#e5e7eb", width: "1px", radius: "8px" },
      header: { background: "#e5e7eb", textColor: "#111827" },
      description: { textColor: "#6b7280", textButtonColor: "#2563eb" },
      price: { amountColor: "#111827", primaryTextColor: "#6b7280", secondaryTextColor: "#9ca3af" },
    },
    planButton: { background: "#2563eb", textColor: "#ffffff" },
    planToggle: { background: "#e5e7eb", activeBackground: "#1f2937", activeText: "#ffffff", inactiveText: "#6b7280" },
  },
  tabs: { activeText: "#2563eb", indicator: "#2563eb", borderColor: "#9ca3af" },
  checkoutBar: {
    background: "#f9fafb",
    borderColor: "#e5e7eb",
    textColor: "#3f3f46",
    buttonBackground: "#2563eb",
    buttonTextColor: "#ffffff",
  },
}

When the Pricing Table is embedded inside the Customer Portal, it automatically uses theme.customerPortal.plans for plan styling so both components stay consistent.


Full example

import { MetrifoxService } from "@metrifox/angular-sdk";

MetrifoxService.initialize({
  clientKey: "your-client-key",
  theme: {
    customerPortal: {
      general: { linkColor: "#2563eb", backgroundColor: "#ffffff" },
      tabs: {
        tabBackground: "#ffffff",
        activeTabBackground: "#2563eb",
        activeTabTextColor: "#ffffff",
        inactiveTabTextColor: "#6b7280",
      },
      sections: {
        background: "#ffffff",
        content: { background: "#f4f4f5", borderRadius: "8px" },
      },
      buttons: {
        primary: { backgroundColor: "#2563eb", typography: { color: "#ffffff" } },
      },
    },
    pricingTable: {
      plans: {
        planCards: { background: "#ffffff", border: { color: "#e5e7eb", radius: "8px" } },
        planButton: { background: "#2563eb", textColor: "#ffffff" },
      },
      tabs: { activeText: "#2563eb", indicator: "#2563eb" },
      checkoutBar: { buttonBackground: "#2563eb", buttonTextColor: "#ffffff" },
    },
  },
});

Per-component overrides (optional):

<metrifox-customer-portal
  [customerKey]="'cust_123'"
  [theme]="{ general: { linkColor: '#1d4ed8' } }"
/>

<metrifox-pricing-table
  [checkoutUsername]="'checkout_user'"
  [productKey]="'prod_key'"
  [theme]="{ plans: { planCards: { background: '#f8fafc' } } }"
/>

Migration from React SDK

| React | Angular | | ----------------------- | ------------------------------ | | metrifoxInit() | MetrifoxService.initialize() | | <CustomerPortal /> | <metrifox-customer-portal> | | <PricingTable /> | <metrifox-pricing-table> | | customerKey prop | [customerKey] input | | onPlanSelect callback | (planSelected) output | | theme prop | [theme] input |


Local Development

Using yalc

For local SDK testing:

# In SDK project
pnpm build
npx yalc publish

# In consuming app
npx yalc add @metrifox/angular-sdk
npm install

Auto-update during development

# In SDK project
pnpm build        # rebuild
npx yalc publish  # re-publish to yalc

# In consuming project
npx yalc update @metrifox/angular-sdk

Clean up

npx yalc remove @metrifox/angular-sdk
npm install

Support

📘 Full Documentation: For detailed guides, API references, and live examples, visit docs.metrifox.com.


📄 License

MIT © MetriFox