{
  "$schema": "https://uipkge.dev/schema/registry-item.json",
  "name": "pricing-usage-calculator-slider",
  "title": "Pricing Usage Calculator Slider",
  "type": "registry:block",
  "files": [
    {
      "path": "packages/registry-angular/blocks/pricing-usage-calculator-slider/pricing-usage-calculator-slider.component.ts",
      "content": "// Infrastructure ROI calculator: MAU / QPS / edge-replica sliders against a\n// traditional monolith cost model. Port of the Vue PricingUsageCalculatorSlider 1:1.\nimport { ChangeDetectionStrategy, Component, Input, computed, signal } from '@angular/core'\nimport { ArrowRight, Calculator, Globe, LucideAngularModule, Server, Users } from 'lucide-angular'\nimport { cn } from '@/lib/utils'\nimport { UiBadgeComponent } from '@/ui/badge/badge.component'\nimport { UiButtonComponent } from '@/ui/button/button.component'\nimport { UiCardComponent } from '@/ui/card/card.component'\n\nexport function formatCompactNumber(num: number): string {\n  if (num >= 1000000) return (num / 1000000).toFixed(1) + 'M'\n  if (num >= 1000) return (num / 1000).toFixed(0) + 'k'\n  return num.toString()\n}\n\n@Component({\n  changeDetection: ChangeDetectionStrategy.Eager,\n  selector: 'ui-pricing-usage-calculator-slider, [ui-pricing-usage-calculator-slider]',\n  standalone: true,\n  host: { '[attr.class]': '\"contents\"' },\n  imports: [LucideAngularModule, UiBadgeComponent, UiButtonComponent, UiCardComponent],\n  template: `\n    <section data-slot=\"pricing-usage-calculator-slider\" [class]=\"rootClass\">\n      <div class=\"mx-auto max-w-6xl space-y-12\">\n        <div class=\"mx-auto max-w-3xl space-y-4 text-center\">\n          <span ui-badge variant=\"secondary\" class=\"gap-1.5 px-3 py-1 font-mono text-xs shadow-xs\">\n            <lucide-icon [img]=\"Calculator\" class=\"text-primary size-3.5\" />\n            Interactive Infrastructure ROI Calculator\n          </span>\n          <h2 class=\"text-foreground text-3xl font-bold tracking-tight sm:text-4xl\">\n            Calculate your annual savings with unbundled architecture.\n          </h2>\n          <p class=\"text-muted-foreground text-base\">\n            See how eliminating proprietary seat licenses and runtime SaaS wrappers cuts your front-end TCO.\n          </p>\n\n          <div class=\"flex flex-wrap items-center justify-center gap-2 pt-2\">\n            <button ui-button size=\"sm\" variant=\"outline\" class=\"font-mono text-xs\" (click)=\"applyPreset('seed')\">\n              Seed Startup (25k MAU)\n            </button>\n            <button ui-button size=\"sm\" variant=\"outline\" class=\"font-mono text-xs\" (click)=\"applyPreset('growth')\">\n              Growth Scale (350k MAU)\n            </button>\n            <button ui-button size=\"sm\" variant=\"outline\" class=\"font-mono text-xs\" (click)=\"applyPreset('scale')\">\n              Hypergrowth (2.5M MAU)\n            </button>\n          </div>\n        </div>\n\n        <div class=\"grid grid-cols-1 items-stretch gap-8 lg:grid-cols-12\">\n          <div\n            ui-card\n            class=\"border-border bg-card/95 flex flex-col justify-between space-y-6 rounded-2xl p-6 text-left shadow-xl sm:p-8 lg:col-span-7\"\n          >\n            <div class=\"space-y-6\">\n              <div class=\"border-border flex items-center justify-between border-b pb-4\">\n                <h3 class=\"text-foreground font-mono text-sm font-bold\">Traffic &amp; Telemetry Inputs</h3>\n                <span class=\"text-muted-foreground font-mono text-xs\">Dynamic Projection</span>\n              </div>\n\n              <div class=\"space-y-2\">\n                <div class=\"flex items-center justify-between font-mono text-xs\">\n                  <span class=\"text-muted-foreground flex items-center gap-1.5\">\n                    <lucide-icon [img]=\"Users\" class=\"text-primary size-3.5\" /> Monthly Active Users (MAU)\n                  </span>\n                  <span class=\"text-foreground text-sm font-bold\">{{ formatNumber(mau()) }} users</span>\n                </div>\n                <input\n                  type=\"range\"\n                  min=\"10000\"\n                  max=\"5000000\"\n                  step=\"25000\"\n                  [value]=\"mau()\"\n                  (input)=\"mau.set($any($event.target).valueAsNumber)\"\n                  class=\"accent-primary bg-border h-2 w-full cursor-pointer rounded-lg\"\n                  aria-label=\"Monthly active users\"\n                />\n              </div>\n\n              <div class=\"space-y-2\">\n                <div class=\"flex items-center justify-between font-mono text-xs\">\n                  <span class=\"text-muted-foreground flex items-center gap-1.5\">\n                    <lucide-icon [img]=\"Server\" class=\"text-primary size-3.5\" /> Peak Query Throughput\n                  </span>\n                  <span class=\"text-foreground text-sm font-bold\">{{ formatNumber(qps()) }} QPS</span>\n                </div>\n                <input\n                  type=\"range\"\n                  min=\"100\"\n                  max=\"20000\"\n                  step=\"100\"\n                  [value]=\"qps()\"\n                  (input)=\"qps.set($any($event.target).valueAsNumber)\"\n                  class=\"accent-primary bg-border h-2 w-full cursor-pointer rounded-lg\"\n                  aria-label=\"Peak query throughput\"\n                />\n              </div>\n\n              <div class=\"space-y-2\">\n                <div class=\"flex items-center justify-between font-mono text-xs\">\n                  <span class=\"text-muted-foreground flex items-center gap-1.5\">\n                    <lucide-icon [img]=\"Globe\" class=\"text-primary size-3.5\" /> Global Edge POP Replicas\n                  </span>\n                  <span class=\"text-foreground text-sm font-bold\">{{ edgeReplicas() }} Edge Regions</span>\n                </div>\n                <input\n                  type=\"range\"\n                  min=\"1\"\n                  max=\"12\"\n                  step=\"1\"\n                  [value]=\"edgeReplicas()\"\n                  (input)=\"edgeReplicas.set($any($event.target).valueAsNumber)\"\n                  class=\"accent-primary bg-border h-2 w-full cursor-pointer rounded-lg\"\n                  aria-label=\"Global edge replicas\"\n                />\n              </div>\n            </div>\n\n            <div\n              class=\"border-border text-muted-foreground flex items-center justify-between border-t pt-4 font-mono text-xs\"\n            >\n              <span>Formula: Direct AST + Raw Static Hosting</span>\n              <span class=\"text-success font-semibold\">✓ Zero Seat Surcharges</span>\n            </div>\n          </div>\n\n          <div\n            ui-card\n            class=\"border-border bg-card/95 flex flex-col justify-between space-y-6 rounded-2xl p-6 text-left shadow-sm sm:p-8 lg:col-span-5\"\n          >\n            <div class=\"space-y-6\">\n              <span ui-badge variant=\"outline\" class=\"border-success/20 bg-success/10 text-success font-mono text-xs\">\n                Projected Annual Net Savings\n              </span>\n\n              <div class=\"space-y-1\">\n                <div class=\"text-success font-mono text-4xl font-bold tracking-tight sm:text-5xl\">\n                  \\${{ annualSavings().toLocaleString() }}\n                </div>\n                <p class=\"text-muted-foreground font-mono text-xs\">\n                  Saved every year (\\${{ monthlySavings().toLocaleString() }}/month)\n                </p>\n              </div>\n\n              <div class=\"space-y-3 pt-2\">\n                <div class=\"space-y-1\">\n                  <div class=\"flex items-center justify-between font-mono text-xs\">\n                    <span class=\"text-destructive font-medium\">Traditional Monolith Stack:</span>\n                    <span class=\"text-foreground font-bold\">\\${{ traditionalCost().toLocaleString() }}/mo</span>\n                  </div>\n                  <div class=\"bg-destructive/20 h-2 overflow-hidden rounded-full\">\n                    <div class=\"bg-destructive h-full w-full\"></div>\n                  </div>\n                </div>\n\n                <div class=\"space-y-1\">\n                  <div class=\"flex items-center justify-between font-mono text-xs\">\n                    <span class=\"text-success font-semibold\">UIPKGE Unbundled Registry:</span>\n                    <span class=\"text-foreground font-bold\">\\${{ uipkgeCost().toLocaleString() }}/mo</span>\n                  </div>\n                  <div class=\"bg-success/20 h-2 overflow-hidden rounded-full\">\n                    <div\n                      class=\"bg-success h-full transition-[width] duration-300\"\n                      [style.width]=\"uipkgeBarWidth() + '%'\"\n                    ></div>\n                  </div>\n                </div>\n              </div>\n            </div>\n\n            <button ui-button class=\"mt-4 h-10 w-full gap-1.5 font-mono text-xs shadow-md\">\n              <span>Lock In Pro Savings</span>\n              <lucide-icon [img]=\"ArrowRight\" class=\"size-3.5\" />\n            </button>\n          </div>\n        </div>\n      </div>\n    </section>\n  `,\n})\nexport class UiPricingUsageCalculatorSliderComponent {\n  protected readonly ArrowRight = ArrowRight\n  protected readonly Calculator = Calculator\n  protected readonly Globe = Globe\n  protected readonly Server = Server\n  protected readonly Users = Users\n\n  @Input('class') className?: string\n\n  readonly mau = signal(100000)\n  readonly qps = signal(500)\n  readonly edgeReplicas = signal(3)\n\n  readonly traditionalCost = computed(() => {\n    const baseSeatFee = 350\n    const perUserFee = (this.mau() / 1000) * 1.8\n    const qpsSurcharge = this.qps() * 0.25\n    return Math.round(baseSeatFee + perUserFee + qpsSurcharge)\n  })\n\n  readonly uipkgeCost = computed(() => {\n    const rawBandwidth = (this.mau() / 100000) * 4\n    const flatProLicense = 24\n    return Math.round(flatProLicense + rawBandwidth)\n  })\n\n  readonly monthlySavings = computed(() => Math.max(0, this.traditionalCost() - this.uipkgeCost()))\n  readonly annualSavings = computed(() => this.monthlySavings() * 12)\n  readonly uipkgeBarWidth = computed(() => Math.max(5, (this.uipkgeCost() / Math.max(1, this.traditionalCost())) * 100))\n\n  get rootClass(): string {\n    return cn('bg-background relative overflow-hidden px-4 py-16 sm:px-6 sm:py-24 lg:px-8', this.className)\n  }\n\n  formatNumber(num: number): string {\n    return formatCompactNumber(num)\n  }\n\n  applyPreset(preset: 'seed' | 'growth' | 'scale'): void {\n    if (preset === 'seed') {\n      this.mau.set(25000)\n      this.qps.set(150)\n      this.edgeReplicas.set(2)\n    } else if (preset === 'growth') {\n      this.mau.set(350000)\n      this.qps.set(2500)\n      this.edgeReplicas.set(5)\n    } else {\n      this.mau.set(2500000)\n      this.qps.set(12000)\n      this.edgeReplicas.set(10)\n    }\n  }\n}\n",
      "type": "registry:block",
      "target": "~/src/app/components/blocks/pricing-usage-calculator-slider/pricing-usage-calculator-slider.component.ts"
    },
    {
      "path": "packages/registry-angular/blocks/pricing-usage-calculator-slider/index.ts",
      "content": "export {\n  UiPricingUsageCalculatorSliderComponent,\n  formatCompactNumber,\n} from './pricing-usage-calculator-slider.component'\n",
      "type": "registry:block",
      "target": "~/src/app/components/blocks/pricing-usage-calculator-slider/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"
  ],
  "description": "Interactive frontend infrastructure ROI calculator with real-time MAU, QPS, and edge replica sliders and annual cost savings scorecard.",
  "categories": [
    "marketing"
  ],
  "deprecated": true,
  "replacedBy": "pricing"
}