{
  "$schema": "https://uipkge.dev/schema/registry-item.json",
  "name": "pricing-feature-tier-slider",
  "title": "Pricing Feature Tier Slider",
  "type": "registry:block",
  "files": [
    {
      "path": "packages/registry-angular/blocks/pricing-feature-tier-slider/pricing-feature-tier-slider.component.ts",
      "content": "// Continuous MAU usage-scale pricing slider: stepped tier calculation with an annual\n// billing toggle and per-tier deliverables. Port of the React block 1:1.\nimport { ChangeDetectionStrategy, Component, Input, computed, signal } from '@angular/core'\nimport { ArrowRight, CheckCircle2, LucideAngularModule, Sliders } from 'lucide-angular'\nimport { cn } from '@/lib/utils'\nimport { UiBadgeComponent } from '@/ui/badge/badge.component'\nimport { UiButtonComponent } from '@/ui/button/button.component'\nimport { UiCardComponent, UiCardContentComponent } from '@/ui/card/card.component'\n\nexport interface PricingTier {\n  label: string\n  mauCount: string\n  basePriceMonthly: number\n  tierName: string\n  features: string[]\n}\n\nconst TIERS: PricingTier[] = [\n  {\n    label: '10K MAU',\n    mauCount: '10,000',\n    basePriceMonthly: 19,\n    tierName: 'Starter Hobbyist',\n    features: [\n      '10,000 Monthly Users',\n      '2 Dedicated Edge Locations',\n      'Community Discord SLA',\n      'Standard 1-Day Log Retention',\n    ],\n  },\n  {\n    label: '50K MAU',\n    mauCount: '50,000',\n    basePriceMonthly: 49,\n    tierName: 'Pro Creator',\n    features: [\n      '50,000 Monthly Users',\n      '12 Global Anycast Edges',\n      'Next-Business-Day Support SLA',\n      '7-Day Immutable Log Retention',\n    ],\n  },\n  {\n    label: '250K MAU',\n    mauCount: '250,000',\n    basePriceMonthly: 149,\n    tierName: 'Growth Scale',\n    features: [\n      '250,000 Monthly Users',\n      'All 36 Global Edge Regions',\n      '4-Hour Priority Engineering SLA',\n      '30-Day SOC2 Audit Logs',\n    ],\n  },\n  {\n    label: '1M MAU',\n    mauCount: '1,000,000',\n    basePriceMonthly: 399,\n    tierName: 'Enterprise Core',\n    features: [\n      '1,000,000 Monthly Users',\n      'Dedicated VPC & Multi-Region Mesh',\n      '15-Minute Critical Incident SLA',\n      '365-Day Cold Storage Logs',\n    ],\n  },\n  {\n    label: '5M+ MAU',\n    mauCount: '5,000,000+',\n    basePriceMonthly: 899,\n    tierName: 'Hyperscale Cluster',\n    features: [\n      '5,000,000+ Monthly Users',\n      'Custom Bare-Metal Cloud Partitions',\n      'Dedicated Solutions Architect',\n      'Custom Security Review & BAA',\n    ],\n  },\n]\n\n@Component({\n  changeDetection: ChangeDetectionStrategy.Eager,\n  selector: 'ui-pricing-feature-tier-slider, [ui-pricing-feature-tier-slider]',\n  standalone: true,\n  // React renders the root <section> itself: the host stays out of layout and `class` goes to the root.\n  host: { '[attr.class]': '\"contents\"' },\n  imports: [LucideAngularModule, UiBadgeComponent, UiButtonComponent, UiCardComponent, UiCardContentComponent],\n  template: `\n    <section data-slot=\"pricing-feature-tier-slider\" [class]=\"rootClass\">\n      <div class=\"mx-auto max-w-7xl px-4 sm:px-6 lg:px-8\">\n        <!-- Section Header -->\n        <div class=\"mx-auto max-w-3xl space-y-4 text-center\">\n          <a\n            href=\"#scale-pricing\"\n            class=\"group border-border/80 bg-secondary/60 hover:bg-secondary text-foreground inline-flex items-center gap-2 rounded-full border px-3.5 py-1 text-xs font-medium shadow-2xs transition-colors\"\n          >\n            <lucide-icon [img]=\"Sliders\" class=\"text-primary size-3.5\" />\n            <span>Continuous Scale Synthesizer</span>\n            <lucide-icon\n              [img]=\"ArrowRight\"\n              class=\"text-muted-foreground size-3 transition-transform group-hover:translate-x-0.5\"\n            />\n          </a>\n\n          <h2 class=\"text-foreground text-3xl font-bold tracking-tight sm:text-4xl\">\n            {{ title() }}\n          </h2>\n\n          <p class=\"text-muted-foreground text-base sm:text-lg\">\n            {{ description() }}\n          </p>\n\n          <!-- Cadence Switcher -->\n          <div class=\"flex items-center justify-center gap-3 pt-2\">\n            <span [class]=\"cadenceLabelClass(!isAnnual())\">Monthly</span>\n            <button\n              type=\"button\"\n              aria-label=\"Toggle annual billing\"\n              [class]=\"cadenceTrackClass()\"\n              (click)=\"isAnnual.set(!isAnnual())\"\n            >\n              <span aria-hidden=\"true\" [class]=\"cadenceThumbClass()\"></span>\n            </button>\n            <span [class]=\"cadenceAnnualLabelClass()\">\n              <span>Annual Billing</span>\n              <span ui-badge variant=\"outline\" class=\"border-success/30 bg-success/10 text-success text-xs\">\n                Save 20%\n              </span>\n            </span>\n          </div>\n        </div>\n\n        <!-- Pricing Slider Main Card -->\n        <div class=\"mx-auto mt-12 max-w-4xl\">\n          <div ui-card class=\"border-border bg-card overflow-hidden shadow-sm\">\n            <div ui-card-content class=\"space-y-8 p-8\">\n              <!-- Scale Indicator Bar -->\n              <div class=\"border-border flex flex-wrap items-center justify-between gap-4 border-b pb-6\">\n                <div class=\"space-y-1\">\n                  <span class=\"text-muted-foreground text-xs font-bold tracking-wider uppercase\"\n                    >Calculated Tier Plan</span\n                  >\n                  <h3 class=\"text-foreground text-2xl font-bold\">{{ currentTier().tierName }}</h3>\n                  <div class=\"text-muted-foreground text-xs\">\n                    Engineered for {{ currentTier().mauCount }} active user sessions\n                  </div>\n                </div>\n\n                <!-- Price Box -->\n                <div class=\"text-right\">\n                  <div class=\"flex items-baseline justify-end gap-1\">\n                    <span class=\"text-foreground font-mono text-4xl font-bold\">&#36;{{ effectivePrice() }}</span>\n                    <span class=\"text-muted-foreground font-mono text-xs\">/ month</span>\n                  </div>\n                  @if (isAnnual()) {\n                    <div class=\"text-success font-mono text-xs font-medium\">\n                      Save &#36;{{ annualSavings() }}/yr on annual\n                    </div>\n                  }\n                </div>\n              </div>\n\n              <!-- Interactive Stepped Range Slider -->\n              <div class=\"space-y-3\">\n                <div class=\"text-foreground flex items-center justify-between text-xs font-bold\">\n                  <span>Monthly Traffic Volume</span>\n                  <span class=\"text-primary font-mono font-bold\">{{ currentTier().mauCount }} Users</span>\n                </div>\n\n                <input\n                  type=\"range\"\n                  min=\"0\"\n                  max=\"4\"\n                  step=\"1\"\n                  aria-label=\"Monthly traffic volume tier\"\n                  [value]=\"sliderIndex()\"\n                  (input)=\"onSliderInput($event)\"\n                  class=\"accent-primary h-2 w-full cursor-pointer\"\n                />\n\n                <!-- Slider Step Labels -->\n                <div class=\"text-muted-foreground flex justify-between font-mono text-xs\">\n                  @for (t of tiers; track t.label) {\n                    <span [class]=\"stepLabelClass(t.label)\" (click)=\"setTierByLabel(t.label)\">\n                      {{ t.label }}\n                    </span>\n                  }\n                </div>\n              </div>\n\n              <!-- Features Checklist Grid for Current Tier -->\n              <div class=\"border-border space-y-3 border-t pt-4\">\n                <span class=\"text-muted-foreground text-xs font-bold tracking-wider uppercase\"\n                  >Guaranteed Tier Deliverables</span\n                >\n                <div class=\"grid grid-cols-1 gap-2.5 sm:grid-cols-2\">\n                  @for (feat of currentTier().features; track $index) {\n                    <div class=\"text-foreground flex items-center gap-2 text-xs\">\n                      <lucide-icon [img]=\"CheckCircle2\" class=\"text-success size-4 shrink-0\" />\n                      <span>{{ feat }}</span>\n                    </div>\n                  }\n                </div>\n              </div>\n\n              <!-- Action Button -->\n              <div class=\"pt-2\">\n                <button ui-button size=\"lg\" class=\"w-full gap-2 shadow-xs\">\n                  <span>Deploy with {{ currentTier().tierName }}</span>\n                  <lucide-icon [img]=\"ArrowRight\" class=\"size-4\" />\n                </button>\n              </div>\n            </div>\n          </div>\n        </div>\n      </div>\n    </section>\n  `,\n})\nexport class UiPricingFeatureTierSliderComponent {\n  protected readonly ArrowRight = ArrowRight\n  protected readonly CheckCircle2 = CheckCircle2\n  protected readonly Sliders = Sliders\n\n  protected readonly tiers = TIERS\n\n  @Input('title') set titleInput(v: string) {\n    if (v !== undefined) this.titleSignal.set(v)\n  }\n  @Input('description') set descriptionInput(v: string) {\n    if (v !== undefined) this.descriptionSignal.set(v)\n  }\n  @Input('class') className?: string\n\n  private readonly titleSignal = signal('Predictable usage pricing with dynamic linear scale.')\n  private readonly descriptionSignal = signal(\n    'Slide to your estimated monthly active users or edge invocations to calculate your exact monthly investment.',\n  )\n\n  readonly title = computed(() => this.titleSignal())\n  readonly description = computed(() => this.descriptionSignal())\n\n  readonly sliderIndex = signal(2)\n  readonly isAnnual = signal(true)\n\n  readonly currentTier = computed(() => TIERS[this.sliderIndex()] ?? TIERS[2]!)\n\n  readonly effectivePrice = computed(() => {\n    const base = this.currentTier().basePriceMonthly\n    return this.isAnnual() ? Math.round(base * 0.8) : base\n  })\n\n  readonly annualSavings = computed(() => (this.currentTier().basePriceMonthly - this.effectivePrice()) * 12)\n\n  get rootClass(): string {\n    return cn('bg-background relative overflow-hidden py-16 sm:py-24', this.className)\n  }\n\n  cadenceLabelClass(active: boolean): string {\n    return cn('text-xs font-medium', active ? 'text-foreground font-semibold' : 'text-muted-foreground')\n  }\n\n  cadenceAnnualLabelClass(): string {\n    return cn(\n      'flex items-center gap-1.5 text-xs font-medium',\n      this.isAnnual() ? 'text-foreground font-semibold' : 'text-muted-foreground',\n    )\n  }\n\n  cadenceTrackClass(): string {\n    return cn(\n      'focus-visible:ring-ring relative inline-flex h-6 w-11 shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus-visible:ring-2 focus-visible:outline-none',\n      this.isAnnual() ? 'bg-primary' : 'bg-muted',\n    )\n  }\n\n  cadenceThumbClass(): string {\n    return cn(\n      'bg-background pointer-events-none inline-block size-5 transform rounded-full shadow-lg ring-0 transition duration-200 ease-in-out',\n      this.isAnnual() ? 'translate-x-5' : 'translate-x-0',\n    )\n  }\n\n  stepLabelClass(label: string): string {\n    return cn(\n      'hover:text-foreground cursor-pointer transition-colors',\n      this.currentTier().label === label ? 'text-primary font-bold' : '',\n    )\n  }\n\n  setTierByLabel(label: string): void {\n    const idx = TIERS.findIndex((t) => t.label === label)\n    if (idx >= 0) this.sliderIndex.set(idx)\n  }\n\n  onSliderInput(event: Event): void {\n    const value = Number((event.target as HTMLInputElement).value)\n    if (Number.isInteger(value) && value >= 0 && value < TIERS.length) this.sliderIndex.set(value)\n  }\n}\n",
      "type": "registry:block",
      "target": "~/src/app/components/blocks/pricing-feature-tier-slider/pricing-feature-tier-slider.component.ts"
    },
    {
      "path": "packages/registry-angular/blocks/pricing-feature-tier-slider/index.ts",
      "content": "export { UiPricingFeatureTierSliderComponent, type PricingTier } from './pricing-feature-tier-slider.component'\n",
      "type": "registry:block",
      "target": "~/src/app/components/blocks/pricing-feature-tier-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": "Continuous MAU and usage scale pricing slider with dynamic tier calculation and annual discount toggle.",
  "categories": [
    "pricing",
    "marketing"
  ]
}