{
  "$schema": "https://uipkge.dev/schema/registry-item.json",
  "name": "cold-chain-temp-monitor",
  "title": "Cold Chain Temp Monitor",
  "type": "registry:block",
  "files": [
    {
      "path": "packages/registry-angular/blocks/cold-chain-temp-monitor/cold-chain-temp-monitor.component.ts",
      "content": "// Refrigerated pharmaceutical & perishable cargo IoT temperature logger and excursion\n// monitoring with multi-reading time-series trend chart, upper/lower threshold\n// guidelines, probe logging history table, and critical excursion alert protocol.\n// Port of the React block 1:1.\nimport { ChangeDetectionStrategy, Component, computed, DestroyRef, inject, Input, signal } from '@angular/core'\nimport {\n  Activity,\n  Battery,\n  Bell,\n  Bluetooth,\n  CheckCircle2,\n  Download,\n  Droplets,\n  Flame,\n  LucideAngularModule,\n  PhoneCall,\n  ShieldAlert,\n  ShieldCheck,\n  Snowflake,\n  ThermometerSnowflake,\n  ThermometerSun,\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  UiCardHeaderComponent,\n  UiCardTitleComponent,\n} from '@/ui/card/card.component'\nimport { UiProgressComponent } from '@/ui/progress/progress.component'\nimport { UiSeparatorComponent } from '@/ui/separator/separator.component'\nimport {\n  UiTableBodyComponent,\n  UiTableCellComponent,\n  UiTableComponent,\n  UiTableHeadComponent,\n  UiTableHeaderComponent,\n  UiTableRowComponent,\n} from '@/ui/table/table.component'\n\nexport interface LogEntry {\n  id: string\n  timestamp: string\n  timeAgo: string\n  internalTemp: number\n  ambientTemp: number\n  deltaT: number\n  probeLocation: string\n  probeId: string\n  humidity: number\n  status: 'optimal' | 'in-spec' | 'warning' | 'breach'\n  isLatest?: boolean\n}\n\nexport interface ChartReading {\n  time: string\n  hourLabel: string\n  internalTemp: number\n  ambientTemp: number\n  milestone: string\n}\n\nconst defaultChartData: ChartReading[] = [\n  { time: '00:00', hourLabel: '00:00 UTC', internalTemp: -19.8, ambientTemp: 18.2, milestone: 'FRA Departure Tarmac' },\n  { time: '03:00', hourLabel: '03:00 UTC', internalTemp: -20.4, ambientTemp: -4.5, milestone: 'Flight EK046 Climb' },\n  {\n    time: '06:00',\n    hourLabel: '06:00 UTC',\n    internalTemp: -20.8,\n    ambientTemp: -6.2,\n    milestone: 'Cruise Flight Level 380',\n  },\n  {\n    time: '09:00',\n    hourLabel: '09:00 UTC',\n    internalTemp: -20.1,\n    ambientTemp: 12.4,\n    milestone: 'DXB Descent & Approach',\n  },\n  {\n    time: '12:00',\n    hourLabel: '12:00 UTC',\n    internalTemp: -19.2,\n    ambientTemp: 38.6,\n    milestone: 'DXB Ramp Tarmac Transfer',\n  },\n  {\n    time: '15:00',\n    hourLabel: '15:00 UTC',\n    internalTemp: -19.6,\n    ambientTemp: 32.0,\n    milestone: 'Perishable Hub Staging',\n  },\n  { time: '18:00', hourLabel: '18:00 UTC', internalTemp: -19.8, ambientTemp: 26.5, milestone: 'Active Reefer Bay #4' },\n  {\n    time: '21:00',\n    hourLabel: '21:00 UTC',\n    internalTemp: -19.5,\n    ambientTemp: 25.0,\n    milestone: 'Pre-Connection QA Inspection',\n  },\n  { time: '24:00', hourLabel: '14:30 UTC', internalTemp: -19.4, ambientTemp: 24.8, milestone: 'Dubai Hub Terminal 2' },\n]\n\nconst defaultLogs: LogEntry[] = [\n  {\n    id: 'log-1',\n    timestamp: 'Aug 21, 14:30 UTC',\n    timeAgo: '24s ago',\n    internalTemp: -19.4,\n    ambientTemp: 24.8,\n    deltaT: 44.2,\n    probeLocation: 'Pallet Center Core',\n    probeId: 'Probe #A1',\n    humidity: 18,\n    status: 'optimal',\n    isLatest: true,\n  },\n  {\n    id: 'log-2',\n    timestamp: 'Aug 21, 14:00 UTC',\n    timeAgo: '30m ago',\n    internalTemp: -19.5,\n    ambientTemp: 25.2,\n    deltaT: 44.7,\n    probeLocation: 'Upper Cargo Lid',\n    probeId: 'Probe #B2',\n    humidity: 18,\n    status: 'optimal',\n  },\n  {\n    id: 'log-3',\n    timestamp: 'Aug 21, 13:30 UTC',\n    timeAgo: '1h ago',\n    internalTemp: -19.2,\n    ambientTemp: 28.4,\n    deltaT: 47.6,\n    probeLocation: 'Lower Ventral Core',\n    probeId: 'Probe #C1',\n    humidity: 19,\n    status: 'in-spec',\n  },\n  {\n    id: 'log-4',\n    timestamp: 'Aug 21, 13:00 UTC',\n    timeAgo: '1.5h ago',\n    internalTemp: -19.8,\n    ambientTemp: 36.1,\n    deltaT: 55.9,\n    probeLocation: 'Pallet Center Core',\n    probeId: 'Probe #A1',\n    humidity: 20,\n    status: 'optimal',\n  },\n  {\n    id: 'log-5',\n    timestamp: 'Aug 21, 12:30 UTC',\n    timeAgo: '2h ago',\n    internalTemp: -20.1,\n    ambientTemp: 38.6,\n    deltaT: 58.7,\n    probeLocation: 'Outer Thermal Jacket',\n    probeId: 'Probe #D4',\n    humidity: 19,\n    status: 'optimal',\n  },\n]\n\n@Component({\n  changeDetection: ChangeDetectionStrategy.Eager,\n  selector: 'ui-cold-chain-temp-monitor, [ui-cold-chain-temp-monitor]',\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    UiCardHeaderComponent,\n    UiCardTitleComponent,\n    UiProgressComponent,\n    UiSeparatorComponent,\n    UiTableBodyComponent,\n    UiTableCellComponent,\n    UiTableComponent,\n    UiTableHeadComponent,\n    UiTableHeaderComponent,\n    UiTableRowComponent,\n  ],\n  template: `\n    <div data-slot=\"cold-chain-temp-monitor\" [class]=\"rootClass\">\n      <!-- Header Section -->\n      <div class=\"flex flex-col gap-4 lg:flex-row lg:items-center lg:justify-between\">\n        <div class=\"space-y-1.5\">\n          <div class=\"flex flex-wrap items-center gap-2.5\">\n            <div class=\"flex items-center gap-2\">\n              <div\n                class=\"border-info/30 bg-info/10 text-info text-info flex size-9 items-center justify-center rounded-lg border shadow-xs\"\n              >\n                <lucide-icon [img]=\"Snowflake\" class=\"size-5\" />\n              </div>\n              <h1 class=\"text-foreground text-2xl font-bold tracking-tight sm:text-3xl\">\n                {{ shipmentTitle }}\n              </h1>\n            </div>\n            <!-- Temperature Class Badge in Sky Blue -->\n            <span\n              ui-badge\n              wrap\n              variant=\"outline\"\n              class=\"border-info/30 bg-info/10 text-info gap-1.5 text-xs font-medium\"\n            >\n              <span class=\"bg-info size-1.5 rounded-full\"></span>\n              <span>{{ tempClass }}</span>\n            </span>\n          </div>\n\n          <div class=\"text-muted-foreground flex flex-wrap items-center gap-x-4 gap-y-1 text-xs\">\n            <div class=\"flex items-center gap-1.5\">\n              <lucide-icon [img]=\"Bluetooth\" class=\"text-primary size-3.5\" />\n              <span class=\"text-foreground font-medium\">{{ beaconId }}</span>\n            </div>\n            <span>·</span>\n            <div class=\"flex items-center gap-1.5\">\n              <lucide-icon [img]=\"Battery\" class=\"text-success size-3.5\" />\n              <span class=\"text-foreground font-medium tabular-nums\">{{ batteryPercent }}%</span>\n              <span>({{ batteryDays }} days remaining)</span>\n            </div>\n            <span>·</span>\n            <div class=\"flex items-center gap-1.5\">\n              <span class=\"relative flex size-2\">\n                <span class=\"bg-success absolute inline-flex h-full w-full rounded-full opacity-75\"></span>\n                <span class=\"bg-success relative inline-flex size-2 rounded-full\"></span>\n              </span>\n              <span class=\"text-foreground font-medium\">Live Telemetry</span>\n              <span>· DXB Terminal 2 Transit</span>\n            </div>\n          </div>\n        </div>\n\n        <!-- Action Button -->\n        <div class=\"flex flex-wrap items-center gap-2.5\">\n          <button\n            ui-button\n            aria-label=\"Download attachment\"\n            variant=\"outline\"\n            size=\"sm\"\n            class=\"gap-2 text-xs font-medium shadow-xs\"\n            [disabled]=\"isExporting()\"\n            (click)=\"handleExportCSV()\"\n          >\n            <lucide-icon [img]=\"Download\" [class]=\"exportIconClass\" />\n            <span>{{ isExporting() ? 'Exporting...' : 'Export Audit Log CSV' }}</span>\n          </button>\n        </div>\n      </div>\n\n      <!-- Export Success Banner -->\n      @if (exportNotification()) {\n        <div\n          class=\"border-border bg-card text-card-foreground flex items-center justify-between gap-x-2 rounded-lg border p-3 text-xs shadow-xs\"\n          role=\"status\"\n        >\n          <div class=\"flex items-center gap-2\">\n            <lucide-icon [img]=\"CheckCircle2\" class=\"text-success size-4 shrink-0\" />\n            <span class=\"text-foreground font-medium\">\n              Cold-chain telemetry audit log exported successfully with cryptographic SHA-256 chain-of-custody seal.\n            </span>\n          </div>\n          <button\n            ui-button\n            aria-label=\"Dismiss notification\"\n            variant=\"ghost\"\n            size=\"icon-sm\"\n            class=\"text-muted-foreground hover:text-foreground size-6\"\n            (click)=\"exportNotification.set(false)\"\n          >\n            <span class=\"text-xs\">✕</span>\n          </button>\n        </div>\n      }\n\n      <!-- 4 Telemetry Overview Cards -->\n      <div class=\"grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4\">\n        <!-- 1. Current Internal Temperature -->\n        <div ui-card class=\"border-border bg-card text-card-foreground shadow-xs\">\n          <div ui-card-header class=\"pb-2\">\n            <div class=\"flex items-center justify-between gap-2\">\n              <div class=\"flex min-w-0 items-center gap-2.5\">\n                <div\n                  class=\"border-info/20 bg-info/10 text-info flex size-8 shrink-0 items-center justify-center rounded-lg border\"\n                >\n                  <lucide-icon [img]=\"ThermometerSnowflake\" class=\"size-4\" />\n                </div>\n                <h3 ui-card-title class=\"truncate text-sm font-medium\">Internal Core Temp</h3>\n              </div>\n              <span ui-badge wrap variant=\"success\" class=\"shrink-0 text-xs\">In Target Zone</span>\n            </div>\n          </div>\n          <div ui-card-content class=\"space-y-2.5 pt-1\">\n            <div class=\"flex flex-wrap items-baseline justify-between gap-x-2 gap-y-0.5\">\n              <div class=\"flex items-baseline gap-1.5\">\n                <span class=\"text-foreground text-3xl font-bold tracking-tight tabular-nums\">\n                  {{ formatTemp(currentInternalTemp) }}°C\n                </span>\n                <span class=\"text-muted-foreground text-xs font-normal\">Payload</span>\n              </div>\n              <span class=\"text-success text-success text-xs font-medium tabular-nums\">±0.6°C setpoint</span>\n            </div>\n\n            <div class=\"border-border/60 border-t pt-2 text-xs\">\n              <div class=\"text-muted-foreground flex items-center justify-between gap-x-2\">\n                <span>Target Corridor:</span>\n                <span class=\"text-foreground font-medium tabular-nums\">-22.0°C to -18.0°C</span>\n              </div>\n              <p class=\"text-muted-foreground mt-0.5 text-xs\">Probe #A1 (Pallet Center Core)</p>\n            </div>\n          </div>\n        </div>\n\n        <!-- 2. Ambient External Temperature -->\n        <div ui-card class=\"border-border bg-card text-card-foreground shadow-xs\">\n          <div ui-card-header class=\"pb-2\">\n            <div class=\"flex items-center justify-between gap-2\">\n              <div class=\"flex min-w-0 items-center gap-2.5\">\n                <div\n                  class=\"border-warning/20 bg-warning/10 text-warning flex size-8 shrink-0 items-center justify-center rounded-lg border\"\n                >\n                  <lucide-icon [img]=\"ThermometerSun\" class=\"size-4\" />\n                </div>\n                <h3 ui-card-title class=\"truncate text-sm font-medium\">Ambient External</h3>\n              </div>\n              <span ui-badge wrap variant=\"outline\" class=\"shrink-0 text-xs\">Dubai Tarmac</span>\n            </div>\n          </div>\n          <div ui-card-content class=\"space-y-2.5 pt-1\">\n            <div class=\"flex flex-wrap items-baseline justify-between gap-x-2 gap-y-0.5\">\n              <div class=\"flex items-baseline gap-1.5\">\n                <span class=\"text-foreground text-3xl font-bold tracking-tight tabular-nums\">\n                  {{ formatTemp(currentAmbientTemp) }}°C\n                </span>\n                <span class=\"text-muted-foreground text-xs font-normal\">Air Temp</span>\n              </div>\n              <div class=\"text-muted-foreground flex items-center gap-1 text-xs font-medium tabular-nums\">\n                <lucide-icon [img]=\"Flame\" class=\"text-warning size-3\" />\n                <span>ΔT 44.2°C</span>\n              </div>\n            </div>\n\n            <div class=\"border-border/60 border-t pt-2 text-xs\">\n              <div class=\"text-muted-foreground flex items-center justify-between gap-x-2\">\n                <span>Transfer Node:</span>\n                <span class=\"text-foreground font-medium\">DXB Cargo T2</span>\n              </div>\n              <p class=\"text-muted-foreground mt-0.5 text-xs\">VIP Cryo-Insulation Envelope Active</p>\n            </div>\n          </div>\n        </div>\n\n        <!-- 3. Relative Humidity -->\n        <div ui-card class=\"border-border bg-card text-card-foreground shadow-xs\">\n          <div ui-card-header class=\"pb-2\">\n            <div class=\"flex items-center justify-between gap-2\">\n              <div class=\"flex min-w-0 items-center gap-2.5\">\n                <div\n                  class=\"flex size-8 shrink-0 items-center justify-center rounded-lg border border-teal-500/20 bg-teal-500/10 text-teal-600 dark:text-teal-400\"\n                >\n                  <lucide-icon [img]=\"Droplets\" class=\"size-4\" />\n                </div>\n                <h3 ui-card-title class=\"truncate text-sm font-medium\">Cargo Humidity</h3>\n              </div>\n              <span ui-badge wrap variant=\"success\" class=\"shrink-0 text-xs\">Optimal Dry</span>\n            </div>\n          </div>\n          <div ui-card-content class=\"space-y-2.5 pt-1\">\n            <div class=\"flex flex-wrap items-baseline justify-between gap-x-2 gap-y-0.5\">\n              <div class=\"flex items-baseline gap-1.5\">\n                <span class=\"text-foreground text-3xl font-bold tracking-tight tabular-nums\"\n                  >{{ currentHumidity }}%</span\n                >\n                <span class=\"text-muted-foreground text-xs font-normal\">RH</span>\n              </div>\n              <span class=\"text-xs font-medium text-teal-600 dark:text-teal-400\">Zero Condensation</span>\n            </div>\n\n            <div class=\"space-y-1\">\n              <div\n                ui-progress\n                [value]=\"currentHumidity\"\n                class=\"h-1.5 [&_[data-slot=progress-indicator]]:bg-teal-500\"\n              ></div>\n              <div class=\"text-muted-foreground flex items-center justify-between gap-x-2 text-xs\">\n                <span>Dew Point: <span class=\"text-foreground font-medium tabular-nums\">-32.4°C</span></span>\n                <span>Spec &lt; 35%</span>\n              </div>\n            </div>\n          </div>\n        </div>\n\n        <!-- 4. Total Excursions / Breach Events -->\n        <div ui-card class=\"border-border bg-card text-card-foreground shadow-xs\">\n          <div ui-card-header class=\"pb-2\">\n            <div class=\"flex items-center justify-between gap-2\">\n              <div class=\"flex min-w-0 items-center gap-2.5\">\n                <div\n                  class=\"border-success/20 bg-success/10 text-success flex size-8 shrink-0 items-center justify-center rounded-lg border\"\n                >\n                  <lucide-icon [img]=\"ShieldCheck\" class=\"size-4\" />\n                </div>\n                <h3 ui-card-title class=\"truncate text-sm font-medium\">Excursion Events</h3>\n              </div>\n              <span ui-badge wrap variant=\"success\" class=\"shrink-0 text-xs\">100% Compliant</span>\n            </div>\n          </div>\n          <div ui-card-content class=\"space-y-2.5 pt-1\">\n            <div class=\"flex flex-wrap items-baseline justify-between gap-x-2 gap-y-0.5\">\n              <div class=\"flex items-baseline gap-1.5\">\n                <span class=\"text-foreground text-3xl font-bold tracking-tight tabular-nums\">{{\n                  totalExcursions\n                }}</span>\n                <span class=\"text-muted-foreground text-xs font-normal\">Breaches</span>\n              </div>\n              <span class=\"text-success text-success text-xs font-medium tabular-nums\">\n                {{ monitoringHours }}h in-transit\n              </span>\n            </div>\n\n            <div class=\"border-border/60 border-t pt-2 text-xs\">\n              <div class=\"text-muted-foreground flex items-center justify-between gap-x-2\">\n                <span>Mean Kinetic Temp (MKT):</span>\n                <span class=\"text-foreground font-medium tabular-nums\">-19.7°C</span>\n              </div>\n              <p class=\"text-muted-foreground mt-0.5 text-xs\">0 cumulative seconds out-of-spec</p>\n            </div>\n          </div>\n        </div>\n      </div>\n\n      <!-- 24-Hour Temperature Curve / Telemetry Graph -->\n      <div ui-card class=\"border-border bg-card text-card-foreground shadow-xs\">\n        <div ui-card-header class=\"pb-3\">\n          <div class=\"flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between\">\n            <div class=\"space-y-1\">\n              <div class=\"flex items-center gap-2\">\n                <lucide-icon [img]=\"Activity\" class=\"text-primary size-4\" />\n                <h3 ui-card-title class=\"text-base font-semibold\">24-Hour Payload & Ambient Telemetry Curve</h3>\n              </div>\n              <p ui-card-description class=\"text-xs\">\n                Continuous thermal gradient monitoring comparing internal core payload against ambient flight & tarmac\n                temperatures with strict excursion threshold corridors.\n              </p>\n            </div>\n\n            <!-- Legend & Timeframe -->\n            <div class=\"flex flex-wrap items-center gap-3\">\n              <div class=\"text-muted-foreground flex flex-wrap items-center gap-3 text-xs\">\n                <div class=\"flex items-center gap-1.5\">\n                  <span class=\"bg-info size-2 rounded-full\"></span>\n                  <span class=\"text-foreground font-medium\">Internal Core</span>\n                </div>\n                <div class=\"flex items-center gap-1.5\">\n                  <span class=\"bg-warning size-2 rounded-full\"></span>\n                  <span>Ambient Air</span>\n                </div>\n                <div class=\"flex items-center gap-1.5\">\n                  <span class=\"border-destructive bg-destructive h-0.5 w-3 border-b border-dashed\"></span>\n                  <span>Upper Limit (-18°C)</span>\n                </div>\n                <div class=\"flex items-center gap-1.5\">\n                  <span class=\"border-info bg-info h-0.5 w-3 border-b border-dashed\"></span>\n                  <span>Lower Limit (-22°C)</span>\n                </div>\n              </div>\n\n              <div class=\"bg-muted border-border/60 flex items-center rounded-lg border p-0.5 text-xs\">\n                @for (tf of timeframes; track tf) {\n                  <button type=\"button\" [class]=\"timeframeClass(tf)\" (click)=\"activeTimeframe.set(tf)\">\n                    {{ tf }}\n                  </button>\n                }\n              </div>\n            </div>\n          </div>\n        </div>\n\n        <div ui-card-content class=\"space-y-4\">\n          <!-- SVG Chart Area -->\n          <div class=\"bg-muted/20 border-border/60 relative w-full overflow-x-auto rounded-lg border p-2 sm:p-4\">\n            <svg class=\"h-64 w-full max-w-[600px] min-w-full\" viewBox=\"0 0 740 220\" preserveAspectRatio=\"none\">\n              <defs>\n                <linearGradient id=\"grad-internal-angular\" x1=\"0\" y1=\"0\" x2=\"0\" y2=\"1\">\n                  <stop offset=\"0%\" stop-color=\"var(--color-sky-500, #0ea5e9)\" stop-opacity=\"0.25\" />\n                  <stop offset=\"100%\" stop-color=\"var(--color-sky-500, #0ea5e9)\" stop-opacity=\"0.0\" />\n                </linearGradient>\n              </defs>\n\n              <!-- Target Corridor Shaded Band (-18°C [y=65] to -22°C [y=155]) -->\n              <rect\n                x=\"40\"\n                y=\"65\"\n                width=\"660\"\n                height=\"90\"\n                fill=\"var(--color-sky-500, #0ea5e9)\"\n                fill-opacity=\"0.06\"\n                rx=\"4\"\n              />\n\n              <!-- Grid Lines -->\n              <line x1=\"40\" y1=\"30\" x2=\"700\" y2=\"30\" stroke=\"currentColor\" class=\"text-border/40\" stroke-width=\"1\" />\n              <line\n                x1=\"40\"\n                y1=\"65\"\n                x2=\"700\"\n                y2=\"65\"\n                stroke=\"var(--color-rose-500, #f43f5e)\"\n                stroke-width=\"1.5\"\n                stroke-dasharray=\"4 4\"\n              />\n              <line\n                x1=\"40\"\n                y1=\"110\"\n                x2=\"700\"\n                y2=\"110\"\n                stroke=\"var(--color-emerald-500, #10b981)\"\n                stroke-width=\"1\"\n                stroke-dasharray=\"2 3\"\n                stroke-opacity=\"0.6\"\n              />\n              <line\n                x1=\"40\"\n                y1=\"155\"\n                x2=\"700\"\n                y2=\"155\"\n                stroke=\"var(--color-sky-600, #0284c7)\"\n                stroke-width=\"1.5\"\n                stroke-dasharray=\"4 4\"\n              />\n              <line x1=\"40\" y1=\"200\" x2=\"700\" y2=\"200\" stroke=\"currentColor\" class=\"text-border/40\" stroke-width=\"1\" />\n\n              <!-- Y-Axis Threshold Labels -->\n              <text x=\"36\" y=\"69\" text-anchor=\"end\" class=\"fill-destructive text-xs font-medium\">-18°C (Max)</text>\n              <text x=\"36\" y=\"113\" text-anchor=\"end\" class=\"dark:fill-success fill-emerald-600 text-xs\">\n                -20°C (Set)\n              </text>\n              <text x=\"36\" y=\"159\" text-anchor=\"end\" class=\"dark:fill-info fill-sky-600 text-xs font-medium\">\n                -22°C (Min)\n              </text>\n\n              <!-- Ambient Temperature Curve (Dashed Amber) -->\n              <path\n                [attr.d]=\"ambientPath()\"\n                fill=\"none\"\n                stroke=\"var(--color-amber-500, #f59e0b)\"\n                stroke-width=\"2\"\n                stroke-dasharray=\"3 3\"\n                stroke-linecap=\"round\"\n              />\n\n              <!-- Internal Temperature Gradient Area & Curve (Solid Sky) -->\n              <path [attr.d]=\"internalArea()\" fill=\"url(#grad-internal-angular)\" />\n              <path\n                [attr.d]=\"internalPath()\"\n                fill=\"none\"\n                stroke=\"var(--color-sky-500, #0ea5e9)\"\n                stroke-width=\"2.5\"\n                stroke-linecap=\"round\"\n                stroke-linejoin=\"round\"\n              />\n\n              <!-- Data Point Markers -->\n              @for (pt of chartPoints(); track $index) {\n                <g>\n                  <!-- Internal Point -->\n                  <circle\n                    [attr.cx]=\"pt.x\"\n                    [attr.cy]=\"pt.yInternal\"\n                    r=\"3.5\"\n                    class=\"stroke-background fill-info cursor-pointer stroke-2 transition-transform hover:scale-125\"\n                    (mouseenter)=\"selectedReadingIndex.set($index)\"\n                  />\n                  <!-- Ambient Point -->\n                  <circle\n                    [attr.cx]=\"pt.x\"\n                    [attr.cy]=\"pt.yAmbient\"\n                    r=\"2.5\"\n                    class=\"stroke-background fill-warning stroke-1\"\n                  />\n                </g>\n              }\n            </svg>\n\n            <!-- X-Axis Timeline Milestones -->\n            <div class=\"mt-2 grid grid-cols-3 gap-2 text-xs sm:grid-cols-5 lg:grid-cols-9\">\n              @for (pt of chartPoints(); track $index) {\n                <div [class]=\"milestoneClass($index)\">\n                  <p class=\"text-foreground font-mono text-xs font-semibold tabular-nums\">{{ pt.time }}</p>\n                  <p class=\"text-muted-foreground truncate text-xs\">{{ pt.milestone }}</p>\n                  <p class=\"text-info text-info font-mono text-xs font-medium tabular-nums\">\n                    {{ formatTemp(pt.internalTemp) }}°C\n                  </p>\n                </div>\n              }\n            </div>\n          </div>\n\n          <!-- Metric Summary Strip -->\n          <div class=\"grid grid-cols-2 gap-3 text-xs sm:grid-cols-4 lg:grid-cols-5\">\n            <div class=\"border-border bg-muted/30 rounded-lg border p-2.5\">\n              <span class=\"text-muted-foreground\">Min Internal Temp</span>\n              <p class=\"text-foreground font-mono text-sm font-semibold tabular-nums\">-20.8°C</p>\n              <span class=\"text-muted-foreground text-xs\">At cruise altitude</span>\n            </div>\n            <div class=\"border-border bg-muted/30 rounded-lg border p-2.5\">\n              <span class=\"text-muted-foreground\">Max Internal Temp</span>\n              <p class=\"text-foreground font-mono text-sm font-semibold tabular-nums\">-19.2°C</p>\n              <span class=\"text-muted-foreground text-xs\">During DXB ramp transfer</span>\n            </div>\n            <div class=\"border-border bg-muted/30 rounded-lg border p-2.5\">\n              <span class=\"text-muted-foreground\">24h Mean Temp</span>\n              <p class=\"text-foreground font-mono text-sm font-semibold tabular-nums\">-19.7°C</p>\n              <span class=\"text-success text-xs font-medium\">Optimal Setpoint</span>\n            </div>\n            <div class=\"border-border bg-muted/30 rounded-lg border p-2.5\">\n              <span class=\"text-muted-foreground\">Standard Deviation</span>\n              <p class=\"text-foreground font-mono text-sm font-semibold tabular-nums\">±0.4°C</p>\n              <span class=\"text-muted-foreground text-xs\">Tight thermal hold</span>\n            </div>\n            <div class=\"border-border bg-muted/30 col-span-2 rounded-lg border p-2.5 sm:col-span-4 lg:col-span-1\">\n              <span class=\"text-muted-foreground\">Peak External Heat</span>\n              <p class=\"text-warning text-warning font-mono text-sm font-semibold tabular-nums\">+38.6°C</p>\n              <span class=\"text-muted-foreground text-xs\">DXB Tarmac 12:00 UTC</span>\n            </div>\n          </div>\n        </div>\n      </div>\n\n      <!-- Temperature Logging History Table & Protocol Card -->\n      <div class=\"grid grid-cols-1 gap-6 lg:grid-cols-3\">\n        <!-- Table: 2 cols on lg -->\n        <div ui-card class=\"border-border bg-card text-card-foreground shadow-xs lg:col-span-2\">\n          <div ui-card-header class=\"pb-3\">\n            <div class=\"flex flex-col gap-1 sm:flex-row sm:items-center sm:justify-between\">\n              <div>\n                <h3 ui-card-title class=\"text-base font-semibold\">Temperature Logging History</h3>\n                <p ui-card-description class=\"text-xs\">\n                  Calibrated multi-probe sensor telemetry pings across core pallet positions.\n                </p>\n              </div>\n              <span ui-badge wrap variant=\"outline\" class=\"w-fit text-xs font-normal tabular-nums\">\n                {{ activeLogs().length }} Recent Pings\n              </span>\n            </div>\n          </div>\n          <div ui-card-content class=\"p-0 sm:p-6 sm:pt-0\">\n            <div class=\"overflow-x-auto\">\n              <table ui-table>\n                <thead ui-table-header>\n                  <tr ui-table-row>\n                    <th ui-table-head class=\"min-w-[140px]\">Timestamp</th>\n                    <th ui-table-head class=\"min-w-[110px]\">Internal Temp</th>\n                    <th ui-table-head class=\"min-w-[100px]\">Ambient Air</th>\n                    <th ui-table-head class=\"min-w-[90px]\">Delta-T</th>\n                    <th ui-table-head class=\"min-w-[150px]\">Probe Location</th>\n                    <th ui-table-head class=\"min-w-[70px]\">RH %</th>\n                    <th ui-table-head class=\"min-w-[90px] text-right\">Status</th>\n                  </tr>\n                </thead>\n                <tbody ui-table-body>\n                  @for (log of activeLogs(); track log.id) {\n                    <tr ui-table-row [class]=\"log.isLatest ? 'bg-muted/30 font-medium' : ''\">\n                      <td ui-table-cell class=\"text-foreground text-xs whitespace-nowrap\">\n                        <div class=\"flex items-center gap-1.5\">\n                          <span class=\"tabular-nums\">{{ log.timestamp }}</span>\n                          @if (log.isLatest) {\n                            <span ui-badge wrap variant=\"secondary\" class=\"h-4 px-1 text-xs font-normal\">Now</span>\n                          }\n                        </div>\n                      </td>\n                      <td ui-table-cell class=\"text-xs whitespace-nowrap\">\n                        <span class=\"text-info text-info font-semibold tabular-nums\">\n                          {{ formatTemp(log.internalTemp) }}°C\n                        </span>\n                      </td>\n                      <td ui-table-cell class=\"text-muted-foreground text-xs whitespace-nowrap tabular-nums\">\n                        {{ formatTemp(log.ambientTemp) }}°C\n                      </td>\n                      <td ui-table-cell class=\"text-foreground text-xs font-medium whitespace-nowrap tabular-nums\">\n                        {{ log.deltaT }}°C\n                      </td>\n                      <td ui-table-cell class=\"text-xs whitespace-nowrap\">\n                        <span class=\"text-foreground\">{{ log.probeLocation }}</span>\n                        <span class=\"text-muted-foreground ml-1 font-mono text-xs\">({{ log.probeId }})</span>\n                      </td>\n                      <td ui-table-cell class=\"text-muted-foreground text-xs whitespace-nowrap tabular-nums\">\n                        {{ log.humidity }}%\n                      </td>\n                      <td ui-table-cell class=\"text-right\">\n                        <span\n                          ui-badge\n                          wrap\n                          [variant]=\"statusVariant(log.status)\"\n                          class=\"text-xs capitalize\"\n                        >\n                          {{ log.status }}\n                        </span>\n                      </td>\n                    </tr>\n                  }\n                </tbody>\n              </table>\n            </div>\n          </div>\n        </div>\n\n        <!-- Critical Excursion Alert Protocol Card -->\n        <div ui-card class=\"border-border bg-card text-card-foreground shadow-xs lg:col-span-1\">\n          <div ui-card-header class=\"pb-3\">\n            <div class=\"flex items-center justify-between gap-x-2\">\n              <div class=\"flex items-center gap-2\">\n                <lucide-icon [img]=\"Bell\" class=\"text-primary size-4\" />\n                <h3 ui-card-title class=\"text-base font-semibold\">Excursion Alert Protocol</h3>\n              </div>\n              <span ui-badge wrap variant=\"success\" class=\"gap-1 text-xs\">\n                <lucide-icon [img]=\"ShieldAlert\" class=\"size-3\" />\n                <span>Armed</span>\n              </span>\n            </div>\n            <p ui-card-description class=\"text-xs\">\n              Automated escalation rules and dry ice reserve endurance monitoring.\n            </p>\n          </div>\n          <div ui-card-content class=\"space-y-4\">\n            <!-- Escalation Rule 1 -->\n            <div class=\"border-border/70 bg-muted/30 space-y-1.5 rounded-lg border p-3 text-xs\">\n              <div class=\"flex items-center justify-between gap-x-2\">\n                <span class=\"text-foreground font-semibold\">Urgent SMS / Pager Alert Trigger:</span>\n                <span ui-badge wrap variant=\"destructive\" class=\"font-mono text-xs\">&gt; -15.0°C</span>\n              </div>\n              <p class=\"text-muted-foreground leading-relaxed\">\n                Triggers priority emergency dispatch if payload core temperature rises above -15.0°C for ≥ 30\n                consecutive minutes.\n              </p>\n            </div>\n\n            <!-- Cryogenic Dry Ice Reserve -->\n            <div class=\"space-y-2 text-xs\">\n              <div class=\"flex items-center justify-between gap-x-2\">\n                <div class=\"flex items-center gap-1.5\">\n                  <lucide-icon [img]=\"Snowflake\" class=\"text-info size-3.5\" />\n                  <span class=\"text-foreground font-medium\">Dry Ice Solid CO2 Reserve</span>\n                </div>\n                <span class=\"text-foreground font-mono font-semibold tabular-nums\"\n                  >{{ dryIceEnduranceHours() }}h hold</span\n                >\n              </div>\n              <div\n                ui-progress\n                [value]=\"dryIceCapacityPercent()\"\n                class=\"[&_[data-slot=progress-indicator]]:bg-info h-2\"\n              ></div>\n              <div class=\"text-muted-foreground flex items-center justify-between gap-x-2\">\n                <span>Sublimation: 0.38 kg/hr</span>\n                <span>42 kg solid reserve</span>\n              </div>\n            </div>\n\n            <div ui-separator></div>\n\n            <!-- Emergency Response Logistics Desk -->\n            <div class=\"border-border bg-muted/40 space-y-2 rounded-lg border p-3 text-xs\">\n              <div class=\"flex items-center justify-between gap-x-2\">\n                <div class=\"flex items-center gap-2\">\n                  <lucide-icon [img]=\"PhoneCall\" class=\"text-primary size-3.5\" />\n                  <span class=\"text-foreground font-semibold\">Rapid Intervention Desk:</span>\n                </div>\n                <span class=\"text-foreground font-medium\">DXB Hub Team</span>\n              </div>\n              <div class=\"text-muted-foreground flex items-center justify-between gap-x-2\">\n                <span>Emergency Pager:</span>\n                <span class=\"text-foreground font-mono font-medium\">+971 4 216 4890</span>\n              </div>\n              <div class=\"text-muted-foreground flex items-center justify-between gap-x-2\">\n                <span>Re-Icing Intervention SLA:</span>\n                <span class=\"text-success font-medium\">&lt; 20 minutes</span>\n              </div>\n              <div\n                class=\"text-muted-foreground border-border/50 flex items-center justify-between gap-x-2 border-t pt-1.5\"\n              >\n                <span>Standard Operating SOP:</span>\n                <span class=\"text-foreground font-mono\">SOP-BIO-904</span>\n              </div>\n            </div>\n          </div>\n        </div>\n      </div>\n    </div>\n  `,\n})\nexport class UiColdChainTempMonitorComponent {\n  protected readonly Activity = Activity\n  protected readonly Battery = Battery\n  protected readonly Bell = Bell\n  protected readonly Bluetooth = Bluetooth\n  protected readonly CheckCircle2 = CheckCircle2\n  protected readonly Download = Download\n  protected readonly Droplets = Droplets\n  protected readonly Flame = Flame\n  protected readonly PhoneCall = PhoneCall\n  protected readonly ShieldAlert = ShieldAlert\n  protected readonly ShieldCheck = ShieldCheck\n  protected readonly Snowflake = Snowflake\n  protected readonly ThermometerSnowflake = ThermometerSnowflake\n  protected readonly ThermometerSun = ThermometerSun\n\n  protected readonly timeframes = ['24h', '48h', '96h'] as const\n\n  @Input() shipmentId = '#CC-9482'\n  @Input() shipmentTitle = 'Vaccine Cold-Chain Consignment #CC-9482'\n  @Input() tempClass = 'Ultra-Cold Frozen · Target: -20°C ± 2°C'\n  @Input() beaconId = 'SensorTag #BT-4892 · BLE 5.3'\n  @Input() protocolVersion = 'IATA CEIV / WHO-PQS Standard'\n  @Input() batteryPercent = 94\n  @Input() batteryDays = 180\n  @Input() currentInternalTemp = -19.4\n  @Input() currentAmbientTemp = 24.8\n  @Input() currentHumidity = 18\n  @Input() totalExcursions = 0\n  @Input() monitoringHours = 96\n  @Input() set logs(v: LogEntry[] | undefined) {\n    this.logsOverride.set(v)\n  }\n  @Input() set chartData(v: ChartReading[] | undefined) {\n    this.chartDataOverride.set(v)\n  }\n  @Input('class') className?: string\n\n  private readonly logsOverride = signal<LogEntry[] | undefined>(undefined)\n  private readonly chartDataOverride = signal<ChartReading[] | undefined>(undefined)\n\n  readonly activeLogs = computed(() => this.logsOverride() ?? defaultLogs)\n  readonly activeChartData = computed(() => this.chartDataOverride() ?? defaultChartData)\n\n  readonly isExporting = signal(false)\n  readonly exportNotification = signal(false)\n  readonly activeTimeframe = signal<'24h' | '48h' | '96h'>('24h')\n  readonly selectedReadingIndex = signal<number | null>(null)\n  readonly dryIceEnduranceHours = signal(72)\n  readonly dryIceCapacityPercent = signal(78)\n\n  private exportTimers: ReturnType<typeof setTimeout>[] = []\n\n  constructor() {\n    inject(DestroyRef).onDestroy(() => this.exportTimers.forEach((t) => clearTimeout(t)))\n  }\n\n  handleExportCSV(): void {\n    this.isExporting.set(true)\n    this.exportTimers.push(\n      setTimeout(() => {\n        this.isExporting.set(false)\n        this.exportNotification.set(true)\n        this.exportTimers.push(\n          setTimeout(() => {\n            this.exportNotification.set(false)\n          }, 4500),\n        )\n      }, 500),\n    )\n  }\n\n  // Coordinate mapping for SVG telemetry chart\n  // Internal Temp scale: -24°C (Y: 200) to -16°C (Y: 20)\n  // Setpoint -20°C -> Y: 110\n  // Upper threshold -18°C -> Y: 65\n  // Lower threshold -22°C -> Y: 155\n  readonly chartPoints = computed(() => {\n    const data = this.activeChartData()\n    const svgWidth = 740\n    const paddingX = 40\n    const usableWidth = svgWidth - paddingX * 2\n\n    return data.map((d, i) => {\n      const x = paddingX + (i / (data.length - 1)) * usableWidth\n      // Map -24°C..-16°C to 195..25\n      // formula: y = 110 - (temp - (-20)) * 22.5\n      const yInternal = 110 - (d.internalTemp - -20) * 22.5\n      // Map ambient -10°C..+45°C to 200..30\n      const yAmbient = 180 - ((d.ambientTemp - -10) / 55) * 150\n\n      return {\n        x,\n        yInternal,\n        yAmbient,\n        ...d,\n      }\n    })\n  })\n\n  readonly internalPath = computed(() => {\n    const pts = this.chartPoints()\n    if (!pts.length) return ''\n    let path = `M ${pts[0].x},${pts[0].yInternal}`\n    for (let i = 1; i < pts.length; i++) {\n      const prev = pts[i - 1]\n      const curr = pts[i]\n      const cx = (prev.x + curr.x) / 2\n      path += ` C ${cx},${prev.yInternal} ${cx},${curr.yInternal} ${curr.x},${curr.yInternal}`\n    }\n    return path\n  })\n\n  readonly internalArea = computed(() => {\n    const pts = this.chartPoints()\n    if (!pts.length) return ''\n    const firstX = pts[0].x\n    const lastX = pts[pts.length - 1].x\n    return `${this.internalPath()} L ${lastX},210 L ${firstX},210 Z`\n  })\n\n  readonly ambientPath = computed(() => {\n    const pts = this.chartPoints()\n    if (!pts.length) return ''\n    let path = `M ${pts[0].x},${pts[0].yAmbient}`\n    for (let i = 1; i < pts.length; i++) {\n      const prev = pts[i - 1]\n      const curr = pts[i]\n      const cx = (prev.x + curr.x) / 2\n      path += ` C ${cx},${prev.yAmbient} ${cx},${curr.yAmbient} ${curr.x},${curr.yAmbient}`\n    }\n    return path\n  })\n\n  get rootClass(): string {\n    return cn('mx-auto w-full max-w-6xl space-y-6', this.className)\n  }\n\n  get exportIconClass(): string {\n    return cn('size-3.5', this.isExporting() && 'animate-bounce')\n  }\n\n  formatTemp(value: number): string {\n    return value > 0 ? `+${value}` : `${value}`\n  }\n\n  statusVariant(status: LogEntry['status']): 'success' | 'outline' | 'warning' {\n    if (status === 'optimal') return 'success'\n    if (status === 'in-spec') return 'outline'\n    return 'warning'\n  }\n\n  timeframeClass(tf: '24h' | '48h' | '96h'): string {\n    return cn(\n      'rounded-md px-2.5 py-1 font-medium transition-colors',\n      this.activeTimeframe() === tf\n        ? 'bg-background text-foreground shadow-xs'\n        : 'text-muted-foreground hover:text-foreground',\n    )\n  }\n\n  milestoneClass(idx: number): string {\n    return cn(\n      'rounded p-1 text-center transition-colors',\n      this.selectedReadingIndex() === idx && 'bg-muted border-border/80 border',\n    )\n  }\n}\n",
      "type": "registry:block",
      "target": "~/src/app/components/blocks/cold-chain-temp-monitor/cold-chain-temp-monitor.component.ts"
    },
    {
      "path": "packages/registry-angular/blocks/cold-chain-temp-monitor/index.ts",
      "content": "export { UiColdChainTempMonitorComponent, type LogEntry, type ChartReading } from './cold-chain-temp-monitor.component'\n",
      "type": "registry:block",
      "target": "~/src/app/components/blocks/cold-chain-temp-monitor/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/progress.json",
    "https://uipkge.dev/r/angular/separator.json",
    "https://uipkge.dev/r/angular/table.json"
  ],
  "description": "Refrigerated pharmaceutical & perishable cargo IoT temperature logger and excursion monitoring with multi-reading time-series trend chart, upper/lower threshold guidelines, probe logging history table, and critical excursion alert protocol.",
  "categories": [
    "logistics",
    "dashboard",
    "app"
  ]
}