{
  "$schema": "https://uipkge.dev/schema/registry-item.json",
  "name": "pricing",
  "title": "Pricing",
  "type": "registry:block",
  "files": [
    {
      "path": "packages/registry-angular/blocks/pricing/pricing.component.ts",
      "content": "// Pricing collection shell: the flagship seat matrix (pricing-01) plus the ten\n// sibling variant blocks, composed into the one install unit that mirrors the\n// 11-file Vue `pricing` registry item. Use `variant` to render a single variant;\n// the default stacks the full collection like the React demo page.\nimport { ChangeDetectionStrategy, Component, Input } from '@angular/core'\nimport { UiPricing01Component } from '../pricing-01/pricing-01.component'\nimport { UiPricingCalculatorComponent } from '../pricing-calculator/pricing-calculator.component'\nimport { UiPricingEnterpriseSlaCardComponent } from '../pricing-enterprise-sla-card/pricing-enterprise-sla-card.component'\nimport { UiPricingFeatureAddonBuilderComponent } from '../pricing-feature-addon-builder/pricing-feature-addon-builder.component'\nimport { UiPricingFeatureTierSliderComponent } from '../pricing-feature-tier-slider/pricing-feature-tier-slider.component'\nimport { UiPricingMatrixGroupedComponent } from '../pricing-matrix-grouped/pricing-matrix-grouped.component'\nimport { UiPricingMatrixPlanCardsComponent } from '../pricing-matrix-plan-cards/pricing-matrix-plan-cards.component'\nimport { UiPricingMatrixStickyHeaderComponent } from '../pricing-matrix-sticky-header/pricing-matrix-sticky-header.component'\nimport { UiPricingSinglePlanComponent } from '../pricing-single-plan/pricing-single-plan.component'\nimport { UiPricingTierComparisonMatrixComponent } from '../pricing-tier-comparison-matrix/pricing-tier-comparison-matrix.component'\nimport { UiPricingUsageCalculatorSliderComponent } from './pricing-usage-calculator-slider.component'\n\nexport type PricingVariant =\n  | 'all'\n  | 'pricing-01'\n  | 'calculator'\n  | 'enterprise-sla'\n  | 'addon-builder'\n  | 'tier-slider'\n  | 'matrix-grouped'\n  | 'matrix-plan-cards'\n  | 'matrix-sticky-header'\n  | 'single-plan'\n  | 'tier-comparison'\n  | 'usage-calculator'\n\n@Component({\n  changeDetection: ChangeDetectionStrategy.Eager,\n  selector: 'ui-pricing, [ui-pricing]',\n  standalone: true,\n  host: { '[attr.class]': '\"contents\"' },\n  imports: [\n    UiPricing01Component,\n    UiPricingCalculatorComponent,\n    UiPricingEnterpriseSlaCardComponent,\n    UiPricingFeatureAddonBuilderComponent,\n    UiPricingFeatureTierSliderComponent,\n    UiPricingMatrixGroupedComponent,\n    UiPricingMatrixPlanCardsComponent,\n    UiPricingMatrixStickyHeaderComponent,\n    UiPricingSinglePlanComponent,\n    UiPricingTierComparisonMatrixComponent,\n    UiPricingUsageCalculatorSliderComponent,\n  ],\n  template: `\n    <div data-slot=\"pricing\" class=\"w-full space-y-16\">\n      @switch (variant) {\n        @case ('pricing-01') {\n          <ui-pricing-01 />\n        }\n        @case ('calculator') {\n          <ui-pricing-calculator />\n        }\n        @case ('enterprise-sla') {\n          <ui-pricing-enterprise-sla-card />\n        }\n        @case ('addon-builder') {\n          <ui-pricing-feature-addon-builder />\n        }\n        @case ('tier-slider') {\n          <ui-pricing-feature-tier-slider />\n        }\n        @case ('matrix-grouped') {\n          <ui-pricing-matrix-grouped />\n        }\n        @case ('matrix-plan-cards') {\n          <ui-pricing-matrix-plan-cards />\n        }\n        @case ('matrix-sticky-header') {\n          <ui-pricing-matrix-sticky-header />\n        }\n        @case ('single-plan') {\n          <ui-pricing-single-plan />\n        }\n        @case ('tier-comparison') {\n          <ui-pricing-tier-comparison-matrix />\n        }\n        @case ('usage-calculator') {\n          <ui-pricing-usage-calculator-slider />\n        }\n        @default {\n          <ui-pricing-01 />\n          <ui-pricing-calculator />\n          <ui-pricing-enterprise-sla-card />\n          <ui-pricing-feature-addon-builder />\n          <ui-pricing-feature-tier-slider />\n          <ui-pricing-matrix-grouped />\n          <ui-pricing-matrix-plan-cards />\n          <ui-pricing-matrix-sticky-header />\n          <ui-pricing-single-plan />\n          <ui-pricing-tier-comparison-matrix />\n          <ui-pricing-usage-calculator-slider />\n        }\n      }\n    </div>\n  `,\n})\nexport class UiPricingComponent {\n  /** Single variant to render, or 'all' for the full stacked collection. */\n  @Input() variant: PricingVariant = 'all'\n}\n",
      "type": "registry:block",
      "target": "~/src/app/components/blocks/pricing/pricing.component.ts"
    },
    {
      "path": "packages/registry-angular/blocks/pricing/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/pricing-usage-calculator-slider.component.ts"
    },
    {
      "path": "packages/registry-angular/blocks/pricing/index.ts",
      "content": "export { UiPricingComponent, type PricingVariant } from './pricing.component'\nexport {\n  UiPricingUsageCalculatorSliderComponent,\n  formatCompactNumber,\n} from './pricing-usage-calculator-slider.component'\n",
      "type": "registry:block",
      "target": "~/src/app/components/blocks/pricing/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/pricing-01.json",
    "https://uipkge.dev/r/angular/pricing-calculator.json",
    "https://uipkge.dev/r/angular/pricing-enterprise-sla-card.json",
    "https://uipkge.dev/r/angular/pricing-feature-addon-builder.json",
    "https://uipkge.dev/r/angular/pricing-feature-tier-slider.json",
    "https://uipkge.dev/r/angular/pricing-matrix-grouped.json",
    "https://uipkge.dev/r/angular/pricing-matrix-plan-cards.json",
    "https://uipkge.dev/r/angular/pricing-matrix-sticky-header.json",
    "https://uipkge.dev/r/angular/pricing-single-plan.json",
    "https://uipkge.dev/r/angular/pricing-tier-comparison-matrix.json"
  ],
  "description": "Pricing collection with eleven interchangeable variants: seat matrix, interactive calculator, enterprise SLA card, feature add-on builder, feature tier slider, grouped matrix, per-plan cards, sticky-header matrix, single plan, tier comparison matrix, and usage calculator slider.",
  "categories": [
    "pricing",
    "marketing",
    "billing"
  ]
}