{
  "$schema": "https://uipkge.dev/schema/registry-item.json",
  "name": "pricing-calculator",
  "title": "Pricing Calculator",
  "type": "registry:block",
  "files": [
    {
      "path": "packages/registry-angular/blocks/pricing-calculator/pricing-calculator.component.ts",
      "content": "// Interactive SaaS and API pricing calculator: seat, request throughput, and cloud storage\n// sliders, annual billing toggle with 20% discount, enterprise add-on switches, automated tier\n// recommendation, and a sticky live estimated cost breakdown. Port of the React block 1:1.\nimport { ChangeDetectionStrategy, Component, Input, computed, signal } from '@angular/core'\nimport {\n  ArrowRight,\n  Check,\n  HardDrive,\n  Headphones,\n  KeyRound,\n  LucideAngularModule,\n  ShieldCheck,\n  Users,\n  Zap,\n} from 'lucide-angular'\nimport { cn } from '@/lib/utils'\nimport { UiBadgeComponent } from '@/ui/badge/badge.component'\nimport { UiButtonComponent } from '@/ui/button/button.component'\nimport {\n  UiCardComponent,\n  UiCardContentComponent,\n  UiCardDescriptionComponent,\n  UiCardFooterComponent,\n  UiCardHeaderComponent,\n  UiCardTitleComponent,\n} from '@/ui/card/card.component'\nimport { UiSeparatorComponent } from '@/ui/separator/separator.component'\nimport { UiSliderComponent } from '@/ui/slider/slider.component'\nimport { UiSwitchComponent } from '@/ui/switch/switch.component'\n\nexport interface PricingCalculatorRequestTier {\n  label: string\n  requests: number\n  cost: number\n}\n\nexport interface PricingCalculatorStorageTier {\n  label: string\n  gb: number\n  cost: number\n}\n\nconst REQUEST_TIERS: PricingCalculatorRequestTier[] = [\n  { label: '10K requests', requests: 10_000, cost: 0 },\n  { label: '50K requests', requests: 50_000, cost: 25 },\n  { label: '100K requests', requests: 100_000, cost: 60 },\n  { label: '250K requests', requests: 250_000, cost: 120 },\n  { label: '500K requests', requests: 500_000, cost: 220 },\n  { label: '1M requests', requests: 1_000_000, cost: 400 },\n  { label: '2.5M requests', requests: 2_500_000, cost: 750 },\n  { label: '5M requests', requests: 5_000_000, cost: 1200 },\n]\n\nconst STORAGE_TIERS: PricingCalculatorStorageTier[] = [\n  { label: '100 GB', gb: 100, cost: 10 },\n  { label: '250 GB', gb: 250, cost: 25 },\n  { label: '500 GB', gb: 500, cost: 45 },\n  { label: '1 TB', gb: 1_000, cost: 80 },\n  { label: '2 TB', gb: 2_000, cost: 150 },\n  { label: '5 TB', gb: 5_000, cost: 320 },\n  { label: '10 TB', gb: 10_000, cost: 580 },\n]\n\nconst SEAT_PRICE = 15\nconst SUPPORT_MANAGER_PRICE = 200\nconst CUSTOM_SLA_PRICE = 500\nconst SSO_PRICE = 100\n\n@Component({\n  changeDetection: ChangeDetectionStrategy.Eager,\n  selector: 'ui-pricing-calculator, [ui-pricing-calculator]',\n  standalone: true,\n  // React renders the root <div> itself: the host stays out of layout and `class` goes to the root.\n  host: { '[attr.class]': '\"contents\"' },\n  imports: [\n    LucideAngularModule,\n    UiBadgeComponent,\n    UiButtonComponent,\n    UiCardComponent,\n    UiCardContentComponent,\n    UiCardDescriptionComponent,\n    UiCardFooterComponent,\n    UiCardHeaderComponent,\n    UiCardTitleComponent,\n    UiSeparatorComponent,\n    UiSliderComponent,\n    UiSwitchComponent,\n  ],\n  template: `\n    <div data-slot=\"pricing-calculator\" [class]=\"rootClass\">\n      <div class=\"flex flex-col items-center gap-4 text-center\">\n        <span ui-badge variant=\"outline\" class=\"gap-1.5 px-3 py-1 text-xs font-medium tracking-wider uppercase\">\n          <lucide-icon [img]=\"ShieldCheck\" class=\"text-primary size-3.5\" />\n          Pricing Calculator\n        </span>\n        <div class=\"space-y-2\">\n          <h2 class=\"text-foreground text-2xl font-bold tracking-tight sm:text-3xl lg:text-4xl\">\n            Interactive Pricing Calculator\n          </h2>\n          <p class=\"text-muted-foreground mx-auto max-w-2xl text-sm sm:text-base\">\n            Calculate your exact monthly or annual investment based on usage.\n          </p>\n        </div>\n\n        <div class=\"border-border bg-card mt-2 inline-flex items-center gap-3 rounded-full border px-4 py-2 shadow-xs\">\n          <span [class]=\"billingLabelClass(!isAnnual())\">Monthly</span>\n          <button\n            ui-switch\n            aria-label=\"Toggle annual billing\"\n            [checked]=\"isAnnual()\"\n            (checkedChange)=\"isAnnual.set($event)\"\n          ></button>\n          <span [class]=\"billingLabelClass(isAnnual())\">Pay Annually</span>\n          <span ui-badge variant=\"secondary\" class=\"bg-primary/10 text-primary border-primary/20 text-xs font-semibold\">\n            Save 20%\n          </span>\n        </div>\n      </div>\n\n      <div class=\"grid grid-cols-1 gap-8 lg:grid-cols-12 lg:items-start\">\n        <div class=\"space-y-6 lg:col-span-7\">\n          <div ui-card>\n            <div ui-card-header>\n              <h3 ui-card-title>Capacity &amp; Scale</h3>\n              <p ui-card-description>Configure team seats, API request throughput, and dedicated storage.</p>\n            </div>\n            <div ui-card-content class=\"space-y-8\">\n              <div class=\"space-y-4\">\n                <div class=\"flex items-center justify-between\">\n                  <div class=\"flex items-center gap-2.5\">\n                    <div\n                      class=\"bg-primary/10 text-primary border-primary/20 flex size-8 shrink-0 items-center justify-center rounded-md border\"\n                    >\n                      <lucide-icon [img]=\"Users\" class=\"size-4\" />\n                    </div>\n                    <div>\n                      <span class=\"text-foreground text-sm font-medium\">Team Seats</span>\n                      <span ui-badge [variant]=\"seatTier().variant\" class=\"ml-2 text-xs font-normal\">\n                        {{ seatTier().label }}\n                      </span>\n                    </div>\n                  </div>\n                  <div class=\"text-right\">\n                    <span class=\"text-foreground text-base font-semibold tabular-nums\">{{ seats() }}</span>\n                    <span class=\"text-muted-foreground text-xs\"> seats (&#36;{{ seats() * seatPrice }}/mo)</span>\n                  </div>\n                </div>\n                <div class=\"pb-6\">\n                  <ui-slider\n                    [value]=\"[seats()]\"\n                    [min]=\"1\"\n                    [max]=\"100\"\n                    [step]=\"1\"\n                    [marks]=\"seatMarks\"\n                    (valueChange)=\"onSeatsChange($event)\"\n                  />\n                </div>\n                <p class=\"text-muted-foreground text-xs\">\n                  Full workspace access, fine-grained permission controls, and audit log tracking for each member.\n                </p>\n              </div>\n\n              <div ui-separator></div>\n\n              <div class=\"space-y-4\">\n                <div class=\"flex items-center justify-between\">\n                  <div class=\"flex items-center gap-2.5\">\n                    <div\n                      class=\"bg-primary/10 text-primary border-primary/20 flex size-8 shrink-0 items-center justify-center rounded-md border\"\n                    >\n                      <lucide-icon [img]=\"Zap\" class=\"size-4\" />\n                    </div>\n                    <div>\n                      <span class=\"text-foreground text-sm font-medium\">Monthly API Requests</span>\n                    </div>\n                  </div>\n                  <div class=\"text-right\">\n                    <span class=\"text-foreground text-base font-semibold tabular-nums\">\n                      {{ currentRequestTier().label }}\n                    </span>\n                    <span class=\"text-muted-foreground text-xs\">\n                      ({{\n                        currentRequestTier().cost === 0 ? 'Included' : '+' + '$' + currentRequestTier().cost + '/mo'\n                      }})\n                    </span>\n                  </div>\n                </div>\n                <div class=\"pb-6\">\n                  <ui-slider\n                    [value]=\"[requestIndex()]\"\n                    [min]=\"0\"\n                    [max]=\"7\"\n                    [step]=\"1\"\n                    [marks]=\"requestMarks\"\n                    (valueChange)=\"onRequestChange($event)\"\n                  />\n                </div>\n                <p class=\"text-muted-foreground text-xs\">\n                  Globally distributed edge endpoints, automatic rate limiting, and sub-50ms p99 latency SLA.\n                </p>\n              </div>\n\n              <div ui-separator></div>\n\n              <div class=\"space-y-4\">\n                <div class=\"flex items-center justify-between\">\n                  <div class=\"flex items-center gap-2.5\">\n                    <div\n                      class=\"bg-primary/10 text-primary border-primary/20 flex size-8 shrink-0 items-center justify-center rounded-md border\"\n                    >\n                      <lucide-icon [img]=\"HardDrive\" class=\"size-4\" />\n                    </div>\n                    <div>\n                      <span class=\"text-foreground text-sm font-medium\">Dedicated Cloud Storage</span>\n                    </div>\n                  </div>\n                  <div class=\"text-right\">\n                    <span class=\"text-foreground text-base font-semibold tabular-nums\">\n                      {{ currentStorageTier().label }}\n                    </span>\n                    <span class=\"text-muted-foreground text-xs\"> (+&#36;{{ currentStorageTier().cost }}/mo)</span>\n                  </div>\n                </div>\n                <div class=\"pb-6\">\n                  <ui-slider\n                    [value]=\"[storageIndex()]\"\n                    [min]=\"0\"\n                    [max]=\"6\"\n                    [step]=\"1\"\n                    [marks]=\"storageMarks\"\n                    (valueChange)=\"onStorageChange($event)\"\n                  />\n                </div>\n                <p class=\"text-muted-foreground text-xs\">\n                  Encrypted at rest (AES-256) with multi-region automated replication and daily disaster backups.\n                </p>\n              </div>\n            </div>\n          </div>\n\n          <div ui-card>\n            <div ui-card-header>\n              <h3 ui-card-title>Enterprise Add-ons</h3>\n              <p ui-card-description>\n                Enhance your infrastructure with enterprise compliance, reliability, and support.\n              </p>\n            </div>\n            <div ui-card-content class=\"space-y-3\">\n              <div\n                class=\"border-border bg-card hover:border-primary/30 flex flex-col justify-between gap-4 rounded-lg border p-4 transition-colors sm:flex-row sm:items-center\"\n              >\n                <div class=\"flex items-start gap-3\">\n                  <div\n                    class=\"bg-primary/10 text-primary border-primary/20 mt-0.5 flex size-8 shrink-0 items-center justify-center rounded-md border\"\n                  >\n                    <lucide-icon [img]=\"Headphones\" class=\"size-4\" />\n                  </div>\n                  <div class=\"space-y-0.5\">\n                    <div class=\"flex items-center gap-2\">\n                      <span class=\"text-foreground text-sm font-medium\">Dedicated Support Manager</span>\n                      <span ui-badge variant=\"outline\" class=\"text-xs font-normal\">+&#36;200/mo</span>\n                    </div>\n                    <p class=\"text-muted-foreground text-xs\">\n                      Direct Slack channel, named technical account manager &amp; 1-hour response SLA.\n                    </p>\n                  </div>\n                </div>\n                <div class=\"flex sm:justify-end\">\n                  <button\n                    ui-switch\n                    aria-label=\"Toggle dedicated support manager add-on\"\n                    [checked]=\"addonSupport()\"\n                    (checkedChange)=\"addonSupport.set($event)\"\n                  ></button>\n                </div>\n              </div>\n\n              <div\n                class=\"border-border bg-card hover:border-primary/30 flex flex-col justify-between gap-4 rounded-lg border p-4 transition-colors sm:flex-row sm:items-center\"\n              >\n                <div class=\"flex items-start gap-3\">\n                  <div\n                    class=\"bg-primary/10 text-primary border-primary/20 mt-0.5 flex size-8 shrink-0 items-center justify-center rounded-md border\"\n                  >\n                    <lucide-icon [img]=\"ShieldCheck\" class=\"size-4\" />\n                  </div>\n                  <div class=\"space-y-0.5\">\n                    <div class=\"flex items-center gap-2\">\n                      <span class=\"text-foreground text-sm font-medium\">Custom SLA Guarantee</span>\n                      <span ui-badge variant=\"outline\" class=\"text-xs font-normal\">+&#36;500/mo</span>\n                    </div>\n                    <p class=\"text-muted-foreground text-xs\">\n                      99.99% uptime guarantee with financial commitments and priority disaster recovery.\n                    </p>\n                  </div>\n                </div>\n                <div class=\"flex sm:justify-end\">\n                  <button\n                    ui-switch\n                    aria-label=\"Toggle custom SLA guarantee add-on\"\n                    [checked]=\"addonSla()\"\n                    (checkedChange)=\"addonSla.set($event)\"\n                  ></button>\n                </div>\n              </div>\n\n              <div\n                class=\"border-border bg-card hover:border-primary/30 flex flex-col justify-between gap-4 rounded-lg border p-4 transition-colors sm:flex-row sm:items-center\"\n              >\n                <div class=\"flex items-start gap-3\">\n                  <div\n                    class=\"bg-primary/10 text-primary border-primary/20 mt-0.5 flex size-8 shrink-0 items-center justify-center rounded-md border\"\n                  >\n                    <lucide-icon [img]=\"KeyRound\" class=\"size-4\" />\n                  </div>\n                  <div class=\"space-y-0.5\">\n                    <div class=\"flex items-center gap-2\">\n                      <span class=\"text-foreground text-sm font-medium\">Single Sign-On (SSO / SAML)</span>\n                      <span ui-badge variant=\"outline\" class=\"text-xs font-normal\">+&#36;100/mo</span>\n                    </div>\n                    <p class=\"text-muted-foreground text-xs\">\n                      Okta, Azure AD, Google Workspace, and SAML 2.0 enterprise identity integration.\n                    </p>\n                  </div>\n                </div>\n                <div class=\"flex sm:justify-end\">\n                  <button\n                    ui-switch\n                    aria-label=\"Toggle SSO add-on\"\n                    [checked]=\"addonSso()\"\n                    (checkedChange)=\"addonSso.set($event)\"\n                  ></button>\n                </div>\n              </div>\n            </div>\n          </div>\n        </div>\n\n        <div class=\"lg:sticky lg:top-8 lg:col-span-5\">\n          <div ui-card class=\"border-border bg-card shadow-xs\">\n            <div ui-card-header class=\"pb-4\">\n              <div class=\"flex items-center justify-between\">\n                <span class=\"text-muted-foreground text-xs font-semibold tracking-wider uppercase\">\n                  Estimated Investment\n                </span>\n                <span ui-badge [variant]=\"recommendedPlan().variant\" class=\"gap-1 shadow-xs\">\n                  @if (recommendedPlan().name === 'Enterprise') {\n                    <lucide-icon [img]=\"ShieldCheck\" class=\"size-3\" />\n                  }\n                  {{ recommendedPlan().badge }}\n                </span>\n              </div>\n              <div class=\"mt-4\">\n                <div class=\"flex items-baseline gap-1.5\">\n                  <span class=\"text-foreground text-4xl font-bold tracking-tight tabular-nums sm:text-5xl\">\n                    &#36;{{ totalMonthly() }}\n                  </span>\n                  <span class=\"text-muted-foreground text-sm font-normal\"> / month</span>\n                </div>\n                @if (isAnnual()) {\n                  <p class=\"text-muted-foreground mt-2 text-xs\">\n                    Billed annually (&#36;{{ totalAnnual().toLocaleString('en-US') }}/yr) ·\n                    <span class=\"text-success font-semibold\"\n                      >Save &#36;{{ annualSavings().toLocaleString('en-US') }}/yr</span\n                    >\n                  </p>\n                } @else {\n                  <p class=\"text-muted-foreground mt-2 text-xs\">\n                    Billed monthly · Switch to annual to save 20% (&#36;{{\n                      annualSavings().toLocaleString('en-US')\n                    }}/yr)\n                  </p>\n                }\n              </div>\n            </div>\n            <div ui-card-content class=\"space-y-4\">\n              <div ui-separator></div>\n              <div class=\"space-y-2.5\">\n                <div class=\"flex items-center justify-between text-sm\">\n                  <span class=\"text-muted-foreground\">Base platform ({{ recommendedPlan().name }})</span>\n                  <span class=\"font-medium tabular-nums\">&#36;{{ annualAdjusted(baseCost()) }}/mo</span>\n                </div>\n                <div class=\"flex items-center justify-between text-sm\">\n                  <span class=\"text-muted-foreground\">Team seats ({{ seats() }} × &#36;{{ seatPrice }})</span>\n                  <span class=\"font-medium tabular-nums\">&#36;{{ annualAdjusted(seatsCost()) }}/mo</span>\n                </div>\n                <div class=\"flex items-center justify-between text-sm\">\n                  <span class=\"text-muted-foreground\">API throughput ({{ currentRequestTier().label }})</span>\n                  <span class=\"font-medium tabular-nums\">\n                    {{ requestsCost() === 0 ? 'Included' : '$' + annualAdjusted(requestsCost()) + '/mo' }}\n                  </span>\n                </div>\n                <div class=\"flex items-center justify-between text-sm\">\n                  <span class=\"text-muted-foreground\">Cloud storage ({{ currentStorageTier().label }})</span>\n                  <span class=\"font-medium tabular-nums\"> &#36;{{ annualAdjusted(storageCost()) }}/mo </span>\n                </div>\n                <div class=\"flex items-center justify-between text-sm\">\n                  <span class=\"text-muted-foreground\">Add-ons ({{ activeAddonsCount() }} active)</span>\n                  <span class=\"font-medium tabular-nums\">\n                    {{ addonsCost() === 0 ? '$0/mo' : '$' + annualAdjusted(addonsCost()) + '/mo' }}\n                  </span>\n                </div>\n                @if (isAnnual()) {\n                  <div\n                    class=\"bg-success/10 text-success flex items-center justify-between rounded-md px-2.5 py-1.5 text-xs font-medium\"\n                  >\n                    <span>Annual discount applied</span>\n                    <span class=\"font-semibold tabular-nums\">20% off</span>\n                  </div>\n                }\n              </div>\n              <div ui-separator></div>\n              <ul class=\"text-muted-foreground space-y-2 text-xs\">\n                <li class=\"flex items-center gap-2\">\n                  <lucide-icon [img]=\"Check\" class=\"text-primary size-3.5 shrink-0\" />\n                  <span>14-day fully featured free trial</span>\n                </li>\n                <li class=\"flex items-center gap-2\">\n                  <lucide-icon [img]=\"Check\" class=\"text-primary size-3.5 shrink-0\" />\n                  <span>No credit card required upfront</span>\n                </li>\n                <li class=\"flex items-center gap-2\">\n                  <lucide-icon [img]=\"Check\" class=\"text-primary size-3.5 shrink-0\" />\n                  <span>Zero-downtime migration assistance</span>\n                </li>\n              </ul>\n            </div>\n            <div ui-card-footer class=\"flex flex-col gap-2.5 pt-2\">\n              <button ui-button class=\"w-full gap-2 font-semibold shadow-xs\" size=\"lg\">\n                Start 14-Day Free Trial\n                <lucide-icon [img]=\"ArrowRight\" class=\"size-4\" />\n              </button>\n              <button ui-button variant=\"outline\" class=\"w-full\" size=\"default\">Request Custom Quote</button>\n            </div>\n          </div>\n        </div>\n      </div>\n    </div>\n  `,\n})\nexport class UiPricingCalculatorComponent {\n  protected readonly ArrowRight = ArrowRight\n  protected readonly Check = Check\n  protected readonly HardDrive = HardDrive\n  protected readonly Headphones = Headphones\n  protected readonly KeyRound = KeyRound\n  protected readonly ShieldCheck = ShieldCheck\n  protected readonly Users = Users\n  protected readonly Zap = Zap\n\n  protected readonly seatPrice = SEAT_PRICE\n  protected readonly seatMarks: Record<number, string> = { 1: '1', 25: '25', 50: '50', 75: '75', 100: '100' }\n  protected readonly requestMarks: Record<number, string> = { 0: '10K', 2: '100K', 4: '500K', 7: '5M' }\n  protected readonly storageMarks: Record<number, string> = { 0: '100 GB', 2: '500 GB', 4: '2 TB', 6: '10 TB' }\n\n  @Input() set initialAnnual(v: boolean) {\n    this.isAnnual.set(!!v)\n  }\n  @Input('class') className?: string\n\n  readonly isAnnual = signal(true)\n  readonly seats = signal(12)\n  readonly requestIndex = signal(2)\n  readonly storageIndex = signal(2)\n  readonly addonSupport = signal(false)\n  readonly addonSla = signal(false)\n  readonly addonSso = signal(true)\n\n  readonly currentRequestTier = computed(() => REQUEST_TIERS[this.requestIndex()] ?? REQUEST_TIERS[0]!)\n  readonly currentStorageTier = computed(() => STORAGE_TIERS[this.storageIndex()] ?? STORAGE_TIERS[0]!)\n\n  readonly seatTier = computed(() => {\n    if (this.seats() <= 5) return { label: 'Starter Team', variant: 'secondary' as const }\n    if (this.seats() <= 25) return { label: 'Growth Team', variant: 'outline' as const }\n    return { label: 'Scale Team', variant: 'default' as const }\n  })\n\n  readonly recommendedPlan = computed(() => {\n    if (this.addonSla() || this.requestIndex() >= 6 || this.storageIndex() >= 5 || this.seats() >= 30) {\n      return { name: 'Enterprise', badge: 'Enterprise Plan', baseFee: 199, variant: 'default' as const }\n    }\n    if (this.seats() >= 8 || this.requestIndex() >= 3 || this.storageIndex() >= 3 || this.addonSupport()) {\n      return { name: 'Growth', badge: 'Growth Plan', baseFee: 79, variant: 'default' as const }\n    }\n    return { name: 'Starter', badge: 'Starter Plan', baseFee: 29, variant: 'secondary' as const }\n  })\n\n  readonly baseCost = computed(() => this.recommendedPlan().baseFee)\n  readonly seatsCost = computed(() => this.seats() * SEAT_PRICE)\n  readonly requestsCost = computed(() => this.currentRequestTier().cost)\n  readonly storageCost = computed(() => this.currentStorageTier().cost)\n  readonly addonsCost = computed(() => {\n    let cost = 0\n    if (this.addonSupport()) cost += SUPPORT_MANAGER_PRICE\n    if (this.addonSla()) cost += CUSTOM_SLA_PRICE\n    if (this.addonSso()) cost += SSO_PRICE\n    return cost\n  })\n\n  readonly activeAddonsCount = computed(() => {\n    let count = 0\n    if (this.addonSupport()) count++\n    if (this.addonSla()) count++\n    if (this.addonSso()) count++\n    return count\n  })\n\n  readonly subtotalMonthly = computed(\n    () => this.baseCost() + this.seatsCost() + this.requestsCost() + this.storageCost() + this.addonsCost(),\n  )\n\n  readonly discountMultiplier = computed(() => (this.isAnnual() ? 0.8 : 1.0))\n  readonly totalMonthly = computed(() => Math.round(this.subtotalMonthly() * this.discountMultiplier()))\n  readonly totalAnnual = computed(() => this.totalMonthly() * 12)\n  readonly annualSavings = computed(() => Math.round(this.subtotalMonthly() * 0.2 * 12))\n\n  get rootClass(): string {\n    return cn('mx-auto w-full max-w-6xl space-y-10 p-4 sm:p-6 lg:p-8', this.className)\n  }\n\n  billingLabelClass(active: boolean): string {\n    return cn(\n      'text-xs font-medium transition-colors',\n      active ? 'text-foreground font-semibold' : 'text-muted-foreground',\n    )\n  }\n\n  annualAdjusted(cost: number): number {\n    return this.isAnnual() ? Math.round(cost * 0.8) : cost\n  }\n\n  onSeatsChange(value: number[]): void {\n    const next = value[0]\n    if (next !== undefined) this.seats.set(next)\n  }\n\n  onRequestChange(value: number[]): void {\n    const next = value[0]\n    if (next !== undefined) this.requestIndex.set(next)\n  }\n\n  onStorageChange(value: number[]): void {\n    const next = value[0]\n    if (next !== undefined) this.storageIndex.set(next)\n  }\n}\n",
      "type": "registry:block",
      "target": "~/src/app/components/blocks/pricing-calculator/pricing-calculator.component.ts"
    },
    {
      "path": "packages/registry-angular/blocks/pricing-calculator/index.ts",
      "content": "export {\n  UiPricingCalculatorComponent,\n  type PricingCalculatorRequestTier,\n  type PricingCalculatorStorageTier,\n} from './pricing-calculator.component'\n",
      "type": "registry:block",
      "target": "~/src/app/components/blocks/pricing-calculator/index.ts"
    }
  ],
  "dependencies": [
    "lucide-angular"
  ],
  "devDependencies": [],
  "registryDependencies": [
    "https://uipkge.dev/r/angular/badge.json",
    "https://uipkge.dev/r/angular/button.json",
    "https://uipkge.dev/r/angular/card.json",
    "https://uipkge.dev/r/angular/separator.json",
    "https://uipkge.dev/r/angular/slider.json",
    "https://uipkge.dev/r/angular/switch.json"
  ],
  "description": "Interactive SaaS and API pricing calculator with dynamic seat, request throughput, and cloud storage sliders, annual billing toggle with 20% discount, enterprise add-on switches, automated tier recommendation, and sticky live estimated cost breakdown.",
  "categories": [
    "marketing",
    "billing"
  ]
}