{
  "$schema": "https://uipkge.dev/schema/registry-item.json",
  "name": "stock-transfer-manager",
  "title": "Stock Transfer Manager",
  "type": "registry:block",
  "files": [
    {
      "path": "packages/registry-angular/blocks/stock-transfer-manager/stock-transfer-manager.component.ts",
      "content": "import { Component, Input, OnInit, computed, signal, ChangeDetectionStrategy } from '@angular/core'\nimport {\n  ArrowRight,\n  Barcode,\n  CheckCircle2,\n  LucideAngularModule,\n  Plus,\n  QrCode,\n  Trash2,\n  Truck,\n  Warehouse,\n} from 'lucide-angular'\nimport { cn } from '@/lib/utils'\nimport { UiBadgeComponent, type BadgeVariant } 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 { UiInputComponent } from '@/ui/input/input.component'\nimport {\n  UiSelectComponent,\n  UiSelectContentComponent,\n  UiSelectItemComponent,\n  UiSelectTriggerComponent,\n  UiSelectValueComponent,\n} from '@/ui/select/select.component'\nimport {\n  UiTableBodyComponent,\n  UiTableCellComponent,\n  UiTableComponent,\n  UiTableHeadComponent,\n  UiTableHeaderComponent,\n  UiTableRowComponent,\n} from '@/ui/table/table.component'\n\nexport type TransferItemCondition = 'sellable' | 'quarantine' | 'damaged'\nexport type StockTransferStatus = 'draft' | 'staged' | 'in_transit' | 'received'\n\nexport interface TransferItem {\n  id: string\n  sku: string\n  name: string\n  barcode: string\n  lotNumber: string\n  sourceBin: string\n  targetBin: string\n  availableQty: number\n  transferQty: number\n  unit: string\n  condition: TransferItemCondition\n}\n\nexport interface StockTransferProps {\n  transferId?: string\n  initialStatus?: StockTransferStatus\n  className?: string\n}\n\n/**\n * Angular port of the React StockTransferManager block: a transfer header card (id, status\n * badge, dispatch / receipt / reset action, origin / destination / shipping selects) above a\n * manifest table with bin routing, editable transfer quantities and item conditions. The\n * scan box adds one unit to the line whose barcode or SKU matches. Edit the sample\n * manifest below.\n */\n@Component({\n  changeDetection: ChangeDetectionStrategy.Eager,\n  selector: 'ui-stock-transfer-manager, [ui-stock-transfer-manager]',\n  standalone: true,\n  host: {\n    '[attr.data-slot]': '\"stock-transfer-manager\"',\n    '[class]': 'hostClass',\n  },\n  imports: [\n    LucideAngularModule,\n    UiBadgeComponent,\n    UiButtonComponent,\n    UiCardComponent,\n    UiCardContentComponent,\n    UiCardDescriptionComponent,\n    UiCardFooterComponent,\n    UiCardHeaderComponent,\n    UiCardTitleComponent,\n    UiInputComponent,\n    UiSelectComponent,\n    UiSelectContentComponent,\n    UiSelectItemComponent,\n    UiSelectTriggerComponent,\n    UiSelectValueComponent,\n    UiTableBodyComponent,\n    UiTableCellComponent,\n    UiTableComponent,\n    UiTableHeadComponent,\n    UiTableHeaderComponent,\n    UiTableRowComponent,\n  ],\n  template: `\n    <!-- Header Summary Card -->\n    <div ui-card>\n      <div ui-card-header class=\"flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between\">\n        <div class=\"space-y-1\">\n          <div class=\"flex items-center gap-2\">\n            <span class=\"text-muted-foreground font-mono text-sm font-medium\">{{ transferId }}</span>\n            <span ui-badge [variant]=\"statusVariant()\" class=\"capitalize\">{{ statusLabel() }}</span>\n          </div>\n          <h3 ui-card-title class=\"text-xl\">Inter-Warehouse Stock Transfer</h3>\n          <p ui-card-description>\n            Transfer goods between fulfillment hubs with bin-level tracking and scan verification.\n          </p>\n        </div>\n        <div class=\"flex items-center gap-2\">\n          @if (status() === 'staged') {\n            <button ui-button variant=\"default\" class=\"gap-2\" (click)=\"status.set('in_transit')\">\n              <lucide-icon [img]=\"Truck\" class=\"size-4\" />\n              Dispatch Transfer\n            </button>\n          }\n          @if (status() === 'in_transit') {\n            <button ui-button variant=\"default\" class=\"gap-2\" (click)=\"status.set('received')\">\n              <lucide-icon [img]=\"CheckCircle2\" class=\"size-4\" />\n              Confirm Receipt\n            </button>\n          }\n          @if (status() === 'received') {\n            <button ui-button variant=\"outline\" class=\"gap-2\" (click)=\"status.set('staged')\">Reset Transfer</button>\n          }\n        </div>\n      </div>\n\n      <div ui-card-content class=\"border-border grid grid-cols-1 gap-4 border-t pt-4 sm:grid-cols-3\">\n        <!-- Source Hub -->\n        <div class=\"border-border space-y-2 rounded-lg border p-3\">\n          <div class=\"text-muted-foreground flex items-center gap-1.5 text-xs font-medium\">\n            <lucide-icon [img]=\"Warehouse\" class=\"size-3.5\" />\n            <span>ORIGIN FACILITY</span>\n          </div>\n          <ui-select\n            [value]=\"sourceWarehouse()\"\n            (valueChange)=\"sourceWarehouse.set($event)\"\n            [disabled]=\"routingLocked()\"\n          >\n            <button ui-select-trigger class=\"w-full\">\n              <ui-select-value placeholder=\"Select origin warehouse\" />\n            </button>\n            <ui-select-content>\n              <ui-select-item value=\"wh-east-01\">East Coast Fulfillment (NJ-01)</ui-select-item>\n              <ui-select-item value=\"wh-west-02\">West Coast Distribution (CA-04)</ui-select-item>\n              <ui-select-item value=\"wh-midwest-03\">Midwest Logistics Hub (IL-02)</ui-select-item>\n            </ui-select-content>\n          </ui-select>\n        </div>\n\n        <!-- Destination Hub -->\n        <div class=\"border-border space-y-2 rounded-lg border p-3\">\n          <div class=\"text-muted-foreground flex items-center gap-1.5 text-xs font-medium\">\n            <lucide-icon [img]=\"ArrowRight\" class=\"size-3.5\" />\n            <span>DESTINATION FACILITY</span>\n          </div>\n          <ui-select\n            [value]=\"targetWarehouse()\"\n            (valueChange)=\"targetWarehouse.set($event)\"\n            [disabled]=\"routingLocked()\"\n          >\n            <button ui-select-trigger class=\"w-full\">\n              <ui-select-value placeholder=\"Select target warehouse\" />\n            </button>\n            <ui-select-content>\n              <ui-select-item value=\"wh-central-02\">Central Distribution Center (TX-01)</ui-select-item>\n              <ui-select-item value=\"wh-north-01\">Northern Sorting Facility (WA-02)</ui-select-item>\n              <ui-select-item value=\"wh-south-03\">Southeast Regional Hub (GA-03)</ui-select-item>\n            </ui-select-content>\n          </ui-select>\n        </div>\n\n        <!-- Carrier / Transport -->\n        <div class=\"border-border space-y-2 rounded-lg border p-3\">\n          <div class=\"text-muted-foreground flex items-center gap-1.5 text-xs font-medium\">\n            <lucide-icon [img]=\"Truck\" class=\"size-3.5\" />\n            <span>SHIPPING METHOD</span>\n          </div>\n          <ui-select [value]=\"transportType()\" (valueChange)=\"transportType.set($event)\" [disabled]=\"routingLocked()\">\n            <button ui-select-trigger class=\"w-full\">\n              <ui-select-value placeholder=\"Select transit mode\" />\n            </button>\n            <ui-select-content>\n              <ui-select-item value=\"pallet_freight\">Dedicated LTL Freight (Palletized)</ui-select-item>\n              <ui-select-item value=\"express_courier\">Priority Courier (Same Day Air)</ui-select-item>\n              <ui-select-item value=\"internal_fleet\">Internal Fleet Transfer (Route 09)</ui-select-item>\n            </ui-select-content>\n          </ui-select>\n        </div>\n      </div>\n    </div>\n\n    <!-- Line Items Table Card -->\n    <div ui-card>\n      <div ui-card-header class=\"flex flex-col gap-3 pb-3 sm:flex-row sm:items-center sm:justify-between\">\n        <div>\n          <h3 ui-card-title class=\"text-base font-semibold\">Manifest Line Items</h3>\n          <p ui-card-description>\n            {{ totalLineItems() }} unique SKUs · {{ totalUnits() }} total units staged for transfer\n          </p>\n        </div>\n\n        <!-- Quick Scan / SKU lookup bar -->\n        <div class=\"flex items-center gap-2\">\n          <div class=\"relative w-64\">\n            <lucide-icon\n              [img]=\"Barcode\"\n              class=\"text-muted-foreground pointer-events-none absolute top-2.5 left-2.5 size-4\"\n            />\n            <ui-input\n              [value]=\"barcodeQuery()\"\n              (valueChange)=\"barcodeQuery.set($event)\"\n              placeholder=\"Scan barcode or SKU...\"\n              class=\"pl-8\"\n              (keydown.enter)=\"handleScan()\"\n            />\n          </div>\n          <button\n            ui-button\n            variant=\"secondary\"\n            size=\"icon\"\n            title=\"Scan Barcode\"\n            aria-label=\"Scan barcode\"\n            (click)=\"handleScan()\"\n          >\n            <lucide-icon [img]=\"QrCode\" class=\"size-4\" />\n          </button>\n          <button ui-button variant=\"outline\" size=\"sm\" class=\"gap-1\" (click)=\"addItem()\">\n            <lucide-icon [img]=\"Plus\" class=\"size-3.5\" />\n            Add Item\n          </button>\n        </div>\n      </div>\n\n      <div ui-card-content class=\"p-0\">\n        <div ui-table>\n          <thead ui-table-header>\n            <tr ui-table-row>\n              <th ui-table-head class=\"w-[280px]\">Product / SKU</th>\n              <th ui-table-head>Lot / Batch</th>\n              <th ui-table-head>Source Bin</th>\n              <th ui-table-head>Target Bin</th>\n              <th ui-table-head class=\"text-right\">Available</th>\n              <th ui-table-head class=\"w-[120px] text-right\">Transfer Qty</th>\n              <th ui-table-head>Condition</th>\n              <th ui-table-head class=\"w-[50px]\"></th>\n            </tr>\n          </thead>\n          <tbody ui-table-body>\n            @for (item of items(); track item.id) {\n              <tr ui-table-row>\n                <!-- SKU + Name -->\n                <td ui-table-cell>\n                  <div class=\"font-medium\">{{ item.name }}</div>\n                  <div class=\"text-muted-foreground flex items-center gap-2 font-mono text-xs\">\n                    <span>{{ item.sku }}</span>\n                    <span>·</span>\n                    <span>{{ item.barcode }}</span>\n                  </div>\n                </td>\n\n                <!-- Lot Number -->\n                <td ui-table-cell>\n                  <span class=\"font-mono text-xs\">{{ item.lotNumber }}</span>\n                </td>\n\n                <!-- Source Bin -->\n                <td ui-table-cell>\n                  <span class=\"bg-muted text-foreground rounded px-1.5 py-0.5 font-mono text-xs font-medium\">{{\n                    item.sourceBin\n                  }}</span>\n                </td>\n\n                <!-- Target Bin -->\n                <td ui-table-cell>\n                  <span\n                    class=\"border-border text-foreground rounded border px-1.5 py-0.5 font-mono text-xs font-medium\"\n                    >{{ item.targetBin }}</span\n                  >\n                </td>\n\n                <!-- Available Qty -->\n                <td ui-table-cell class=\"text-muted-foreground text-right font-mono text-xs\">\n                  {{ item.availableQty }} {{ item.unit }}\n                </td>\n\n                <!-- Transfer Qty Input -->\n                <td ui-table-cell class=\"text-right\">\n                  <ui-input\n                    type=\"number\"\n                    [min]=\"1\"\n                    [max]=\"item.availableQty\"\n                    [value]=\"item.transferQty\"\n                    (valueChange)=\"updateItemQty(item.id, $event)\"\n                    class=\"h-8 text-right font-mono\"\n                    [disabled]=\"status() === 'received'\"\n                  />\n                </td>\n\n                <!-- Condition -->\n                <td ui-table-cell>\n                  <ui-select\n                    [value]=\"item.condition\"\n                    (valueChange)=\"updateItemCondition(item.id, $event)\"\n                    [disabled]=\"status() === 'received'\"\n                  >\n                    <button ui-select-trigger class=\"h-8 w-[110px] text-xs capitalize\">\n                      <ui-select-value />\n                    </button>\n                    <ui-select-content>\n                      <ui-select-item value=\"sellable\">Sellable</ui-select-item>\n                      <ui-select-item value=\"quarantine\">Quarantine</ui-select-item>\n                      <ui-select-item value=\"damaged\">Damaged</ui-select-item>\n                    </ui-select-content>\n                  </ui-select>\n                </td>\n\n                <!-- Remove Action -->\n                <td ui-table-cell>\n                  <button\n                    ui-button\n                    variant=\"ghost\"\n                    size=\"icon\"\n                    class=\"text-muted-foreground hover:text-destructive size-8\"\n                    [disabled]=\"status() === 'received'\"\n                    [attr.aria-label]=\"'Remove ' + item.sku\"\n                    (click)=\"removeItem(item.id)\"\n                  >\n                    <lucide-icon [img]=\"Trash2\" class=\"size-4\" />\n                  </button>\n                </td>\n              </tr>\n            }\n          </tbody>\n        </div>\n      </div>\n\n      <div\n        ui-card-footer\n        class=\"border-border text-muted-foreground flex items-center justify-between border-t py-3 text-xs\"\n      >\n        <div>All inventory movements are recorded in immutable ledger log #LOG-9402.</div>\n        <div class=\"text-foreground font-medium\">\n          Total: <span class=\"font-mono\">{{ totalUnits() }}</span> items across\n          <span class=\"font-mono\">{{ totalLineItems() }}</span> positions\n        </div>\n      </div>\n    </div>\n  `,\n})\nexport class UiStockTransferManagerComponent implements OnInit {\n  @Input() transferId = 'TRF-2026-8841'\n  @Input() initialStatus: StockTransferStatus = 'staged'\n  @Input('class') className?: string\n\n  protected readonly ArrowRight = ArrowRight\n  protected readonly Barcode = Barcode\n  protected readonly CheckCircle2 = CheckCircle2\n  protected readonly Plus = Plus\n  protected readonly QrCode = QrCode\n  protected readonly Trash2 = Trash2\n  protected readonly Truck = Truck\n  protected readonly Warehouse = Warehouse\n\n  readonly status = signal<StockTransferStatus>('staged')\n  readonly sourceWarehouse = signal('wh-east-01')\n  readonly targetWarehouse = signal('wh-central-02')\n  readonly transportType = signal('pallet_freight')\n  readonly barcodeQuery = signal('')\n\n  readonly items = signal<TransferItem[]>([\n    {\n      id: 'itm-1',\n      sku: 'SKU-LOGI-884',\n      name: 'Industrial Barcode Scanner IP65',\n      barcode: '079357318921',\n      lotNumber: 'LOT-2026-A1',\n      sourceBin: 'A-04-R2-B12',\n      targetBin: 'C-01-R1-B03',\n      availableQty: 140,\n      transferQty: 25,\n      unit: 'pcs',\n      condition: 'sellable',\n    },\n    {\n      id: 'itm-2',\n      sku: 'SKU-PWR-331',\n      name: 'Lithium Iron Battery Pack 48V',\n      barcode: '079357318945',\n      lotNumber: 'LOT-2025-X9',\n      sourceBin: 'B-12-R4-B01',\n      targetBin: 'D-08-R2-B09',\n      availableQty: 48,\n      transferQty: 12,\n      unit: 'units',\n      condition: 'sellable',\n    },\n    {\n      id: 'itm-3',\n      sku: 'SKU-SENS-102',\n      name: 'Optical Proximity Sensor M18',\n      barcode: '079357318988',\n      lotNumber: 'LOT-2026-C4',\n      sourceBin: 'A-02-R1-B06',\n      targetBin: 'A-09-R3-B02',\n      availableQty: 320,\n      transferQty: 80,\n      unit: 'pcs',\n      condition: 'sellable',\n    },\n  ])\n\n  readonly totalUnits = computed(() => this.items().reduce((sum, item) => sum + Number(item.transferQty || 0), 0))\n  readonly totalLineItems = computed(() => this.items().length)\n\n  /** Origin, destination and shipping method can only change before dispatch. */\n  readonly routingLocked = computed(() => this.status() !== 'draft' && this.status() !== 'staged')\n\n  /** React seeds its status state from `initialStatus` once, on mount. */\n  ngOnInit(): void {\n    this.status.set(this.initialStatus)\n  }\n\n  get hostClass(): string {\n    return cn('block w-full space-y-6', this.className)\n  }\n\n  protected statusVariant(): BadgeVariant {\n    const status = this.status()\n    return status === 'received' ? 'default' : status === 'in_transit' ? 'secondary' : 'outline'\n  }\n\n  protected statusLabel(): string {\n    return this.status().replace('_', ' ')\n  }\n\n  addItem(): void {\n    this.items.update((prev) => [\n      ...prev,\n      {\n        id: `itm-${Date.now()}`,\n        sku: 'SKU-GEN-001',\n        name: 'Standard Packing Material Kit',\n        barcode: '079357399999',\n        lotNumber: 'LOT-UNASSIGNED',\n        sourceBin: 'A-01-R1-B01',\n        targetBin: 'B-01-R1-B01',\n        availableQty: 100,\n        transferQty: 10,\n        unit: 'kits',\n        condition: 'sellable',\n      },\n    ])\n  }\n\n  removeItem(id: string): void {\n    this.items.update((prev) => prev.filter((i) => i.id !== id))\n  }\n\n  updateItemQty(id: string, qty: string | number): void {\n    const transferQty = Number(qty)\n    this.items.update((prev) => prev.map((i) => (i.id === id ? { ...i, transferQty } : i)))\n  }\n\n  updateItemCondition(id: string, condition: string): void {\n    this.items.update((prev) =>\n      prev.map((i) => (i.id === id ? { ...i, condition: condition as TransferItemCondition } : i)),\n    )\n  }\n\n  handleScan(): void {\n    const query = this.barcodeQuery()\n    if (!query) return\n    this.items.update((prev) =>\n      prev.map((i) => (i.barcode === query || i.sku === query ? { ...i, transferQty: i.transferQty + 1 } : i)),\n    )\n    this.barcodeQuery.set('')\n  }\n}\n",
      "type": "registry:block",
      "target": "~/src/app/components/blocks/stock-transfer-manager/stock-transfer-manager.component.ts"
    },
    {
      "path": "packages/registry-angular/blocks/stock-transfer-manager/index.ts",
      "content": "export { UiStockTransferManagerComponent } from './stock-transfer-manager.component'\nexport type {\n  TransferItem,\n  TransferItemCondition,\n  StockTransferProps,\n  StockTransferStatus,\n} from './stock-transfer-manager.component'\n",
      "type": "registry:block",
      "target": "~/src/app/components/blocks/stock-transfer-manager/index.ts"
    }
  ],
  "dependencies": [
    "lucide-angular"
  ],
  "devDependencies": [],
  "registryDependencies": [
    "https://uipkge.dev/r/angular/card.json",
    "https://uipkge.dev/r/angular/button.json",
    "https://uipkge.dev/r/angular/input.json",
    "https://uipkge.dev/r/angular/badge.json",
    "https://uipkge.dev/r/angular/select.json",
    "https://uipkge.dev/r/angular/table.json"
  ],
  "description": "Inter-facility inventory transfer console with bin-level routing, barcode lookup, and condition classification.",
  "categories": [
    "dashboard",
    "data-display"
  ]
}