{
  "$schema": "https://uipkge.dev/schema/registry-item.json",
  "name": "packing-slip-generator",
  "title": "Packing Slip Generator",
  "type": "registry:block",
  "files": [
    {
      "path": "packages/registry-angular/blocks/packing-slip-generator/packing-slip-generator.component.ts",
      "content": "// Shopify / ShipStation style warehouse order packing slip with an interactive picker\n// verification checklist: warehouse header, ship-to / origin / carrier routing grid, picker\n// pack-station ribbon with a simulated Code-128 barcode, itemized pick list table with packed\n// checkboxes, carton specs, returns notice and a QC inspector stamp. Port of the React block 1:1.\nimport { ChangeDetectionStrategy, Component, Input, computed, signal } from '@angular/core'\nimport {\n  Box,\n  Building2,\n  Check,\n  CheckCheck,\n  CheckCircle2,\n  Clock,\n  Copy,\n  FileDown,\n  LucideAngularModule,\n  MapPin,\n  Printer,\n  QrCode,\n  RotateCcw,\n  Scan,\n  ShieldCheck,\n  Tag,\n  Truck,\n  User,\n  Warehouse,\n  Zap,\n} from 'lucide-angular'\nimport { cn } from '@/lib/utils'\nimport { UiBadgeComponent } from '@/ui/badge/badge.component'\nimport { UiButtonComponent } from '@/ui/button/button.component'\nimport { UiCheckboxComponent } from '@/ui/checkbox/checkbox.component'\nimport { UiSeparatorComponent } from '@/ui/separator/separator.component'\nimport {\n  UiTableBodyComponent,\n  UiTableCellComponent,\n  UiTableComponent,\n  UiTableFooterComponent,\n  UiTableHeadComponent,\n  UiTableHeaderComponent,\n  UiTableRowComponent,\n} from '@/ui/table/table.component'\n\nexport interface PackingSlipItem {\n  id: string\n  sku: string\n  barcode: string\n  name: string\n  variant: string\n  location: string\n  qtyOrdered: number\n  qtyPacked: number\n  weightLbs: number\n  notes?: string\n  initialPacked?: boolean\n}\n\nexport interface PackingSlipGeneratorInputs {\n  packingSlipNo?: string\n  orderNo?: string\n  carrier?: string\n  carrierService?: string\n  trackingNo?: string\n  orderDate?: string\n  shipDate?: string\n  warehouseName?: string\n  warehouseFacility?: string\n  warehouseAddress?: string\n  warehousePhone?: string\n  warehouseEmail?: string\n  customerName?: string\n  customerCompany?: string\n  customerAddress?: string\n  customerPhone?: string\n  customerEmail?: string\n  deliveryNotes?: string\n  pickerName?: string\n  pickerId?: string\n  packStation?: string\n  shift?: string\n  boxSize?: string\n  dunnageType?: string\n  qcInspector?: string\n  qcStamp?: string\n  qcTimestamp?: string\n  items?: PackingSlipItem[]\n  showActions?: boolean\n  initialPackedAll?: boolean\n}\n\nconst defaultItems: PackingSlipItem[] = [\n  {\n    id: 'item-1',\n    sku: '#SKU-84920',\n    barcode: '849201928410',\n    name: 'Aero Minimalist Runner',\n    variant: 'Size 10.5 · Matte Black',\n    location: 'Aisle 04 · Rack B · Shelf 02',\n    qtyOrdered: 1,\n    qtyPacked: 1,\n    weightLbs: 1.8,\n    notes: 'Eco-Knit Upper / EVA Cushioning Sole',\n    initialPacked: true,\n  },\n  {\n    id: 'item-2',\n    sku: '#SKU-77219',\n    barcode: '772198421093',\n    name: 'HydroShield Waterproof Shell Jacket',\n    variant: \"Men's M · Alpine Green\",\n    location: 'Aisle 02 · Rack D · Shelf 01',\n    qtyOrdered: 1,\n    qtyPacked: 1,\n    weightLbs: 1.6,\n    notes: '3-Layer DWR Membrane / Sealed Seams',\n    initialPacked: true,\n  },\n  {\n    id: 'item-3',\n    sku: '#SKU-31904',\n    barcode: '319045812903',\n    name: 'Ergonomic Trail Crew Socks (3-Pack)',\n    variant: 'Charcoal / Grey · L',\n    location: 'Aisle 08 · Rack A · Shelf 04',\n    qtyOrdered: 1,\n    qtyPacked: 1,\n    weightLbs: 1.4,\n    notes: 'Merino Wool Blend / Seamless Toe',\n    initialPacked: false,\n  },\n]\n\nfunction buildPackedMap(items: PackingSlipItem[], packedAll: boolean): Record<string, boolean> {\n  const map: Record<string, boolean> = {}\n  for (const item of items) map[item.id] = packedAll ? true : (item.initialPacked ?? false)\n  return map\n}\n\n@Component({\n  changeDetection: ChangeDetectionStrategy.Eager,\n  selector: 'ui-packing-slip-generator, [ui-packing-slip-generator]',\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    UiCheckboxComponent,\n    UiSeparatorComponent,\n    UiTableBodyComponent,\n    UiTableCellComponent,\n    UiTableComponent,\n    UiTableFooterComponent,\n    UiTableHeadComponent,\n    UiTableHeaderComponent,\n    UiTableRowComponent,\n  ],\n  template: `\n    <div data-slot=\"packing-slip-generator\" [class]=\"rootClass\">\n      <!-- Top Action & Fulfillment Toolbar (Screen Only) -->\n      @if (showActions()) {\n        <div\n          class=\"no-print border-border bg-card flex flex-col gap-4 rounded-xl border p-4 shadow-xs sm:flex-row sm:items-center sm:justify-between\"\n        >\n          <div class=\"flex flex-wrap items-center gap-3\">\n            <div class=\"flex items-center gap-2\">\n              <span class=\"text-foreground font-mono text-sm font-semibold tracking-tight\">{{ packingSlipNo() }}</span>\n              <span ui-badge variant=\"outline\" class=\"gap-1 font-mono text-xs\">\n                <lucide-icon [img]=\"Tag\" class=\"text-muted-foreground size-3\" />\n                {{ orderNo() }}\n              </span>\n            </div>\n\n            <ui-separator orientation=\"vertical\" class=\"hidden h-4 sm:block\" />\n\n            <div class=\"text-muted-foreground flex items-center gap-1.5 text-xs\">\n              <lucide-icon [img]=\"Truck\" class=\"text-primary size-3.5\" />\n              <span class=\"text-foreground font-medium\">{{ carrierService() }}</span>\n            </div>\n\n            <span ui-badge [variant]=\"isAllPacked() ? 'default' : 'secondary'\" class=\"gap-1 text-xs font-medium\">\n              @if (isAllPacked()) {\n                <lucide-icon [img]=\"CheckCircle2\" class=\"size-3\" />\n              } @else {\n                <lucide-icon [img]=\"Clock\" class=\"size-3\" />\n              }\n              {{\n                isAllPacked()\n                  ? 'All Items Verified'\n                  : verifiedItemsCount() + '/' + effectiveItems().length + ' Packed (' + progressPercentage() + '%)'\n              }}\n            </span>\n          </div>\n\n          <div class=\"flex flex-wrap items-center gap-2\">\n            <button\n              ui-button\n              type=\"button\"\n              variant=\"outline\"\n              size=\"sm\"\n              class=\"gap-1.5 text-xs font-medium\"\n              (click)=\"isAllPacked() ? resetPackingChecklist() : markAllPacked()\"\n            >\n              @if (isAllPacked()) {\n                <lucide-icon [img]=\"RotateCcw\" class=\"size-3.5\" />\n              } @else {\n                <lucide-icon [img]=\"CheckCheck\" class=\"size-3.5\" />\n              }\n              {{ isAllPacked() ? 'Reset Checklist' : 'Verify All' }}\n            </button>\n\n            <button\n              ui-button\n              aria-label=\"Download attachment\"\n              type=\"button\"\n              variant=\"outline\"\n              size=\"sm\"\n              class=\"gap-1.5 text-xs font-medium\"\n              [disabled]=\"isDownloading()\"\n              (click)=\"handleDownloadPdf()\"\n            >\n              <lucide-icon [img]=\"FileDown\" class=\"size-3.5\" />\n              {{ isDownloading() ? 'Generating PDF...' : 'Download PDF' }}\n            </button>\n\n            <button ui-button type=\"button\" size=\"sm\" class=\"gap-1.5 text-xs font-medium\" (click)=\"handlePrint()\">\n              <lucide-icon [img]=\"Printer\" class=\"size-3.5\" />\n              Print 4x6 Slip\n            </button>\n          </div>\n        </div>\n      }\n\n      <!-- Printable Packing Slip Paper Container -->\n      <div\n        class=\"packing-slip-paper border-border bg-card mx-auto w-full max-w-4xl space-y-6 rounded-xl border p-6 shadow-md transition-shadow sm:p-8\"\n      >\n        <!-- Section 1: Warehouse & Slip Header -->\n        <div class=\"flex flex-col gap-6 sm:flex-row sm:items-start sm:justify-between\">\n          <div class=\"space-y-2\">\n            <div class=\"flex items-center gap-2.5\">\n              <div\n                class=\"bg-primary text-primary-foreground flex size-10 items-center justify-center rounded-lg shadow-xs\"\n              >\n                <lucide-icon [img]=\"Warehouse\" class=\"size-5\" />\n              </div>\n              <div>\n                <h2 class=\"text-foreground text-base font-semibold tracking-tight sm:text-lg\">\n                  {{ warehouseName() }}\n                </h2>\n                <p class=\"text-muted-foreground text-xs\">{{ warehouseFacility() }}</p>\n              </div>\n            </div>\n            <div class=\"text-muted-foreground text-xs\">\n              <p>{{ warehouseAddress() }}</p>\n              <p class=\"mt-0.5\">{{ warehousePhone() }} · {{ warehouseEmail() }}</p>\n            </div>\n          </div>\n\n          <div class=\"flex flex-col items-start gap-3 sm:items-end\">\n            <div\n              class=\"border-primary/20 bg-primary/5 text-primary inline-flex items-center rounded-md border px-2.5 py-1 text-xs font-semibold\"\n            >\n              COMMERCIAL PACKING SLIP\n            </div>\n            <div class=\"space-y-1 text-left text-xs sm:text-right\">\n              <div class=\"flex items-center gap-2 sm:justify-end\">\n                <span class=\"text-muted-foreground\">Packing Slip Ref:</span>\n                <span class=\"text-foreground font-mono font-semibold\">{{ packingSlipNo() }}</span>\n              </div>\n              <div class=\"flex items-center gap-2 sm:justify-end\">\n                <span class=\"text-muted-foreground\">Order Reference:</span>\n                <span class=\"text-foreground font-mono font-semibold\">{{ orderNo() }}</span>\n              </div>\n              <div class=\"flex items-center gap-2 sm:justify-end\">\n                <span class=\"text-muted-foreground\">Order Date:</span>\n                <span class=\"text-foreground font-medium\">{{ orderDate() }}</span>\n              </div>\n              <div class=\"flex items-center gap-2 sm:justify-end\">\n                <span class=\"text-muted-foreground\">Ship Date:</span>\n                <span class=\"text-foreground font-medium\">{{ shipDate() }}</span>\n              </div>\n            </div>\n          </div>\n        </div>\n\n        <ui-separator />\n\n        <!-- Section 2: Routing Grid (Ship-To, Origin, Carrier) -->\n        <div class=\"grid grid-cols-1 gap-4 md:grid-cols-3\">\n          <div class=\"border-border/80 bg-muted/20 rounded-lg border p-4\">\n            <div class=\"text-muted-foreground mb-2.5 flex items-center gap-2 text-xs font-medium\">\n              <lucide-icon [img]=\"User\" class=\"text-primary size-3.5\" />\n              Ship-To Recipient\n            </div>\n            <div class=\"space-y-1 text-xs\">\n              <p class=\"text-foreground text-sm font-semibold\">{{ customerName() }}</p>\n              <p class=\"text-foreground/80 font-medium\">{{ customerCompany() }}</p>\n              <p class=\"text-muted-foreground\">{{ customerAddress() }}</p>\n              <p class=\"text-muted-foreground\">{{ customerPhone() }}</p>\n              @if (deliveryNotes()) {\n                <div class=\"border-warning/20 bg-warning/10 text-warning mt-2.5 rounded border p-2\">\n                  <p class=\"text-xs font-semibold\">Delivery Note:</p>\n                  <p class=\"text-xs\">{{ deliveryNotes() }}</p>\n                </div>\n              }\n            </div>\n          </div>\n\n          <div class=\"border-border/80 bg-muted/20 rounded-lg border p-4\">\n            <div class=\"text-muted-foreground mb-2.5 flex items-center gap-2 text-xs font-medium\">\n              <lucide-icon [img]=\"Building2\" class=\"text-primary size-3.5\" />\n              Fulfillment Origin\n            </div>\n            <div class=\"space-y-1 text-xs\">\n              <p class=\"text-foreground text-sm font-semibold\">{{ warehouseName() }}</p>\n              <p class=\"text-foreground/80 font-medium\">Outbound Logistics Dock #12</p>\n              <p class=\"text-muted-foreground\">{{ warehouseAddress() }}</p>\n              <p class=\"text-muted-foreground\">Support: {{ warehousePhone() }}</p>\n              <div class=\"text-muted-foreground mt-2.5 flex items-center gap-1.5 text-xs\">\n                <lucide-icon [img]=\"Zap\" class=\"text-success size-3\" />\n                <span>Direct EDI Dispatch Cleared</span>\n              </div>\n            </div>\n          </div>\n\n          <div class=\"border-border/80 bg-muted/20 rounded-lg border p-4\">\n            <div class=\"text-muted-foreground mb-2.5 flex items-center gap-2 text-xs font-medium\">\n              <lucide-icon [img]=\"Truck\" class=\"text-primary size-3.5\" />\n              Carrier & Service\n            </div>\n            <div class=\"space-y-2 text-xs\">\n              <div>\n                <p class=\"text-foreground text-sm font-semibold\">{{ carrierService() }}</p>\n                <p class=\"text-muted-foreground\">Standard Air Parcel · Guaranteed</p>\n              </div>\n              <div>\n                <span class=\"text-muted-foreground\">Tracking Number:</span>\n                <div class=\"mt-1 flex items-center gap-2\">\n                  <span class=\"text-foreground font-mono text-xs font-semibold\">{{ trackingNo() }}</span>\n                  <button\n                    type=\"button\"\n                    class=\"no-print border-border hover:bg-muted focus-visible:ring-ring inline-flex size-6 items-center justify-center rounded border focus-visible:ring-2 focus-visible:outline-none\"\n                    title=\"Copy Tracking Number\"\n                    (click)=\"copyTrackingNumber()\"\n                  >\n                    @if (copiedTracking()) {\n                      <lucide-icon [img]=\"Check\" class=\"text-muted-foreground size-3\" />\n                    } @else {\n                      <lucide-icon [img]=\"Copy\" class=\"text-muted-foreground size-3\" />\n                    }\n                  </button>\n                </div>\n              </div>\n              <div\n                class=\"text-muted-foreground border-border/40 flex items-center justify-between border-t pt-1 text-xs\"\n              >\n                <span>Billing: Prepaid</span>\n                <span class=\"font-mono\">Declared: $349.00</span>\n              </div>\n            </div>\n          </div>\n        </div>\n\n        <!-- Section 3: Picker & Pack Station Ribbon -->\n        <div\n          class=\"border-border bg-muted/40 flex flex-col gap-4 rounded-lg border p-4 sm:flex-row sm:items-center sm:justify-between\"\n        >\n          <div class=\"flex flex-wrap items-center gap-4\">\n            <div class=\"space-y-0.5\">\n              <div class=\"text-muted-foreground flex items-center gap-1.5 text-xs font-medium\">\n                <lucide-icon [img]=\"User\" class=\"text-primary size-3.5\" />\n                Picker & Station\n              </div>\n              <p class=\"text-foreground text-sm font-semibold\">\n                {{ pickerName() }}\n                <span class=\"text-muted-foreground font-mono text-xs font-normal\">({{ pickerId() }})</span>\n              </p>\n              <p class=\"text-muted-foreground text-xs\">{{ packStation() }} · {{ shift() }}</p>\n            </div>\n\n            <ui-separator orientation=\"vertical\" class=\"hidden h-10 md:block\" />\n\n            <div class=\"space-y-0.5\">\n              <div class=\"text-muted-foreground flex items-center gap-1.5 text-xs font-medium\">\n                <lucide-icon [img]=\"Scan\" class=\"text-primary size-3.5\" />\n                Packing Progress\n              </div>\n              <div class=\"flex items-center gap-2\">\n                <div class=\"bg-muted border-border/50 h-2 w-28 overflow-hidden rounded-full border\">\n                  <div\n                    class=\"bg-primary h-full transition-[width] duration-300\"\n                    [style.width.%]=\"progressPercentage()\"\n                  ></div>\n                </div>\n                <span class=\"text-foreground font-mono text-xs font-semibold tabular-nums\">\n                  {{ verifiedItemsCount() }}/{{ effectiveItems().length }} Verified\n                </span>\n              </div>\n            </div>\n          </div>\n\n          <div\n            class=\"border-border/60 bg-background/80 flex flex-col items-center justify-center rounded border px-3 py-2 text-center shadow-2xs sm:items-end\"\n          >\n            <div class=\"flex h-8 items-center gap-[2px]\" aria-label=\"Barcode\">\n              <span class=\"bg-foreground h-8 w-[3px]\"></span>\n              <span class=\"h-8 w-[1px] bg-transparent\"></span>\n              <span class=\"bg-foreground h-8 w-[2px]\"></span>\n              <span class=\"h-8 w-[1px] bg-transparent\"></span>\n              <span class=\"bg-foreground h-8 w-[4px]\"></span>\n              <span class=\"h-8 w-[2px] bg-transparent\"></span>\n              <span class=\"bg-foreground h-8 w-[1px]\"></span>\n              <span class=\"bg-foreground h-8 w-[3px]\"></span>\n              <span class=\"h-8 w-[1px] bg-transparent\"></span>\n              <span class=\"bg-foreground h-8 w-[5px]\"></span>\n              <span class=\"h-8 w-[2px] bg-transparent\"></span>\n              <span class=\"bg-foreground h-8 w-[2px]\"></span>\n              <span class=\"h-8 w-[1px] bg-transparent\"></span>\n              <span class=\"bg-foreground h-8 w-[4px]\"></span>\n              <span class=\"h-8 w-[2px] bg-transparent\"></span>\n              <span class=\"bg-foreground h-8 w-[3px]\"></span>\n              <span class=\"h-8 w-[1px] bg-transparent\"></span>\n              <span class=\"bg-foreground h-8 w-[5px]\"></span>\n              <span class=\"h-8 w-[2px] bg-transparent\"></span>\n              <span class=\"bg-foreground h-8 w-[2px]\"></span>\n              <span class=\"h-8 w-[1px] bg-transparent\"></span>\n              <span class=\"bg-foreground h-8 w-[3px]\"></span>\n              <span class=\"h-8 w-[1px] bg-transparent\"></span>\n              <span class=\"bg-foreground h-8 w-[4px]\"></span>\n              <span class=\"h-8 w-[2px] bg-transparent\"></span>\n              <span class=\"bg-foreground h-8 w-[5px]\"></span>\n              <span class=\"h-8 w-[1px] bg-transparent\"></span>\n              <span class=\"bg-foreground h-8 w-[3px]\"></span>\n              <span class=\"h-8 w-[2px] bg-transparent\"></span>\n              <span class=\"bg-foreground h-8 w-[4px]\"></span>\n              <span class=\"h-8 w-[1px] bg-transparent\"></span>\n              <span class=\"bg-foreground h-8 w-[2px]\"></span>\n              <span class=\"h-8 w-[2px] bg-transparent\"></span>\n              <span class=\"bg-foreground h-8 w-[5px]\"></span>\n              <span class=\"h-8 w-[1px] bg-transparent\"></span>\n              <span class=\"bg-foreground h-8 w-[3px]\"></span>\n            </div>\n            <p class=\"text-foreground font-mono text-xs font-semibold tracking-widest\">*{{ barcodeRef() }}*</p>\n          </div>\n        </div>\n\n        <!-- Section 4: Itemized Pick List Table -->\n        <div class=\"space-y-2\">\n          <div class=\"flex items-center justify-between\">\n            <div class=\"flex items-center gap-2\">\n              <h3 class=\"text-foreground text-sm font-semibold tracking-tight\">Itemized Pick & Pack Checklist</h3>\n              <span ui-badge variant=\"outline\" class=\"font-mono text-xs\">\n                {{ effectiveItems().length }} Line Items\n              </span>\n            </div>\n            <span class=\"text-muted-foreground text-xs\">Check items upon bin scan and physical carton packing</span>\n          </div>\n\n          <div class=\"border-border overflow-hidden rounded-lg border\">\n            <div class=\"overflow-x-auto\">\n              <table ui-table>\n                <thead ui-table-header class=\"bg-muted/40\">\n                  <tr ui-table-row>\n                    <th ui-table-head class=\"w-12 text-center\">Packed</th>\n                    <th ui-table-head class=\"w-48\">Bin / Location</th>\n                    <th ui-table-head class=\"w-36\">SKU & Barcode</th>\n                    <th ui-table-head>Item Name & Variant Details</th>\n                    <th ui-table-head class=\"w-28 text-center\">Qty Pick/Ord</th>\n                    <th ui-table-head class=\"w-24 text-right\">Weight</th>\n                  </tr>\n                </thead>\n                <tbody ui-table-body>\n                  @for (item of effectiveItems(); track item.id) {\n                    <tr ui-table-row [class]=\"rowClass(item.id)\" (click)=\"toggleItemPacked(item.id)\">\n                      <td ui-table-cell class=\"text-center\" (click)=\"$event.stopPropagation()\">\n                        <div class=\"flex items-center justify-center\">\n                          <ui-checkbox\n                            [id]=\"'chk-' + item.id\"\n                            [checked]=\"!!packedState()[item.id]\"\n                            (checkedChange)=\"setItemPacked(item.id, $event)\"\n                          />\n                        </div>\n                      </td>\n                      <td ui-table-cell>\n                        <div\n                          class=\"border-border bg-muted/60 text-foreground inline-flex items-center gap-1.5 rounded-md border px-2 py-1 text-xs font-medium\"\n                        >\n                          <lucide-icon [img]=\"MapPin\" class=\"text-primary size-3 shrink-0\" />\n                          <span>{{ item.location }}</span>\n                        </div>\n                      </td>\n                      <td ui-table-cell>\n                        <div class=\"space-y-0.5\">\n                          <p class=\"text-foreground font-mono text-xs font-semibold\">{{ item.sku }}</p>\n                          <p class=\"text-muted-foreground font-mono text-xs\">UPC: {{ item.barcode }}</p>\n                        </div>\n                      </td>\n                      <td ui-table-cell>\n                        <div class=\"space-y-0.5\">\n                          <p [class]=\"itemNameClass(item.id)\">{{ item.name }}</p>\n                          <p class=\"text-muted-foreground text-xs\">{{ item.variant }}</p>\n                          @if (item.notes) {\n                            <p class=\"text-muted-foreground/80 text-xs italic\">{{ item.notes }}</p>\n                          }\n                        </div>\n                      </td>\n                      <td ui-table-cell class=\"text-center\">\n                        <div\n                          class=\"border-border/80 bg-background text-foreground inline-flex items-center gap-1 rounded border px-2 py-0.5 font-mono text-xs font-semibold shadow-2xs\"\n                        >\n                          <span [class]=\"packedState()[item.id] ? 'text-primary' : 'text-foreground'\">{{\n                            packedState()[item.id] ? item.qtyPacked : 0\n                          }}</span>\n                          <span class=\"text-muted-foreground font-normal\">/</span>\n                          <span class=\"tabular-nums\">{{ item.qtyOrdered }}</span>\n                        </div>\n                      </td>\n                      <td ui-table-cell class=\"text-right\">\n                        <span class=\"text-foreground font-mono text-xs font-medium tabular-nums\">\n                          {{ item.weightLbs.toFixed(1) }} lbs\n                        </span>\n                      </td>\n                    </tr>\n                  }\n                </tbody>\n                <tfoot ui-table-footer class=\"bg-muted/50 font-medium\">\n                  <tr ui-table-row>\n                    <td ui-table-cell colspan=\"4\" class=\"text-foreground text-left text-xs font-semibold\">\n                      Order Package Totals ({{ effectiveItems().length }} Distinct SKUs)\n                    </td>\n                    <td ui-table-cell class=\"text-foreground text-center font-mono text-xs font-semibold tabular-nums\">\n                      {{ totalPackedUnits() }} / {{ totalOrderedUnits() }} Units\n                    </td>\n                    <td ui-table-cell class=\"text-foreground text-right font-mono text-xs font-semibold tabular-nums\">\n                      {{ totalWeightLabel() }}\n                    </td>\n                  </tr>\n                </tfoot>\n              </table>\n            </div>\n          </div>\n        </div>\n\n        <!-- Section 5: Package Summary & Quality Control Certification -->\n        <div class=\"grid grid-cols-1 gap-4 md:grid-cols-3\">\n          <div class=\"border-border/80 bg-muted/20 space-y-2 rounded-lg border p-4\">\n            <div class=\"text-muted-foreground flex items-center gap-2 text-xs font-medium\">\n              <lucide-icon [img]=\"Box\" class=\"text-primary size-3.5\" />\n              Carton Specifications\n            </div>\n            <div class=\"space-y-1.5 text-xs\">\n              <div class=\"flex items-center justify-between\">\n                <span class=\"text-muted-foreground\">Packing Box:</span>\n                <span class=\"text-foreground font-medium\">{{ boxSize() }}</span>\n              </div>\n              <div class=\"flex items-center justify-between\">\n                <span class=\"text-muted-foreground\">Total Units:</span>\n                <span class=\"text-foreground font-mono font-semibold\">{{ totalOrderedUnits() }} items</span>\n              </div>\n              <div class=\"flex items-center justify-between\">\n                <span class=\"text-muted-foreground\">Gross Weight:</span>\n                <span class=\"text-foreground font-mono font-semibold\">{{ totalWeightLabel() }}</span>\n              </div>\n              <div class=\"flex items-center justify-between\">\n                <span class=\"text-muted-foreground\">Void Fill / Dunnage:</span>\n                <span class=\"text-muted-foreground\">{{ dunnageType() }}</span>\n              </div>\n            </div>\n          </div>\n\n          <div class=\"border-border/80 bg-muted/20 space-y-2 rounded-lg border p-4\">\n            <div class=\"text-muted-foreground flex items-center gap-2 text-xs font-medium\">\n              <lucide-icon [img]=\"QrCode\" class=\"text-primary size-3.5\" />\n              Hassle-Free Returns\n            </div>\n            <div class=\"text-muted-foreground space-y-1 text-xs\">\n              <p class=\"text-foreground font-medium\">Need to make an exchange or return?</p>\n              <p>\n                Scan the QR code or visit <span class=\"text-foreground font-mono\">apexretail.com/returns</span> within\n                30 days.\n              </p>\n              <p class=\"text-muted-foreground/90 pt-1 text-xs\">\n                Please include this packing slip with items in original condition.\n              </p>\n            </div>\n          </div>\n\n          <div class=\"border-border/80 bg-muted/20 flex flex-col items-center justify-center rounded-lg border p-4\">\n            <div\n              class=\"border-success/70 bg-success/10 border-success/70 bg-success/15 w-full rotate-[-1.5deg] rounded-lg border-2 border-dashed p-3 text-center transition-transform hover:rotate-0\"\n            >\n              <div class=\"text-success flex items-center justify-center gap-1.5\">\n                <lucide-icon [img]=\"ShieldCheck\" class=\"size-4 shrink-0\" />\n                <span class=\"font-mono text-xs font-semibold tracking-widest uppercase\">{{ qcStamp() }}</span>\n              </div>\n              <p class=\"text-success dark:text-foreground mt-1 font-mono text-xs font-semibold\">AUDITED & SEALED</p>\n              <p class=\"text-success/80 mt-0.5 text-xs\">Inspector: {{ qcInspector() }}</p>\n              <p class=\"text-success/70 font-mono text-xs\">{{ qcTimestamp() }}</p>\n            </div>\n          </div>\n        </div>\n\n        <!-- Section 6: Document Footer Note -->\n        <div\n          class=\"border-border text-muted-foreground flex flex-col items-center justify-between gap-2 border-t pt-4 text-xs sm:flex-row\"\n        >\n          <p>Generated by Apex Logistics WMS v4.8.2 · Station ID: {{ packStation() }}</p>\n          <p class=\"font-mono\">DOC ID: PS-2026-849201-US-04 · Barcode Validated</p>\n        </div>\n      </div>\n    </div>\n  `,\n})\nexport class UiPackingSlipGeneratorComponent {\n  protected readonly Box = Box\n  protected readonly Building2 = Building2\n  protected readonly Check = Check\n  protected readonly CheckCheck = CheckCheck\n  protected readonly CheckCircle2 = CheckCircle2\n  protected readonly Clock = Clock\n  protected readonly Copy = Copy\n  protected readonly FileDown = FileDown\n  protected readonly MapPin = MapPin\n  protected readonly Printer = Printer\n  protected readonly QrCode = QrCode\n  protected readonly RotateCcw = RotateCcw\n  protected readonly Scan = Scan\n  protected readonly ShieldCheck = ShieldCheck\n  protected readonly Tag = Tag\n  protected readonly Truck = Truck\n  protected readonly User = User\n  protected readonly Warehouse = Warehouse\n  protected readonly Zap = Zap\n\n  readonly packingSlipNo = signal('#PS-849201')\n  readonly orderNo = signal('#ORD-92841')\n  readonly carrier = signal('FedEx')\n  readonly carrierService = signal('FedEx 2-Day Air')\n  readonly trackingNo = signal('7849 2018 9284 1029')\n  readonly orderDate = signal('Aug 21, 2026')\n  readonly shipDate = signal('Aug 21, 2026')\n  readonly warehouseName = signal('Apex Retail Warehouse #04')\n  readonly warehouseFacility = signal('West Coast Omnichannel Hub')\n  readonly warehouseAddress = signal('1040 North Industry Pkwy, Reno, NV 89502')\n  readonly warehousePhone = signal('+1 (800) 555-0199')\n  readonly warehouseEmail = signal('fulfillment-reno4@apexretail.io')\n  readonly customerName = signal('Eleanor Vance')\n  readonly customerCompany = signal('Vance Design Studios · Suite 400')\n  readonly customerAddress = signal('742 Evergreen Terrace, Springfield, OR 97477')\n  readonly customerPhone = signal('+1 (555) 839-2019')\n  readonly customerEmail = signal('eleanor.vance@vancestudios.design')\n  readonly deliveryNotes = signal('Gate Code: #4829. Leave at covered front porch if unavailable. Do not bend.')\n  readonly pickerName = signal('Marcus Vance')\n  readonly pickerId = signal('#EMP-4821')\n  readonly packStation = signal('Pack Station #4')\n  readonly shift = signal('Morning Shift · Bay Alpha')\n  readonly boxSize = signal('Box #3 · 14\" × 10\" × 6\"')\n  readonly dunnageType = signal('Recycled Kraft Void Fill (1.2 oz)')\n  readonly qcInspector = signal('Elena Rostova (#QC-89)')\n  readonly qcStamp = signal('QC Passed · Station #4')\n  readonly qcTimestamp = signal('2026-08-21 09:42 PST')\n  readonly showActions = signal(true)\n  readonly initialPackedAll = signal(false)\n\n  private readonly itemsInput = signal<PackingSlipItem[] | undefined>(undefined)\n\n  @Input('packingSlipNo') set packingSlipNoAttr(v: string | undefined) {\n    if (v !== undefined) this.packingSlipNo.set(v)\n  }\n  @Input('orderNo') set orderNoAttr(v: string | undefined) {\n    if (v !== undefined) this.orderNo.set(v)\n  }\n  @Input('carrier') set carrierAttr(v: string | undefined) {\n    if (v !== undefined) this.carrier.set(v)\n  }\n  @Input('carrierService') set carrierServiceAttr(v: string | undefined) {\n    if (v !== undefined) this.carrierService.set(v)\n  }\n  @Input('trackingNo') set trackingNoAttr(v: string | undefined) {\n    if (v !== undefined) this.trackingNo.set(v)\n  }\n  @Input('orderDate') set orderDateAttr(v: string | undefined) {\n    if (v !== undefined) this.orderDate.set(v)\n  }\n  @Input('shipDate') set shipDateAttr(v: string | undefined) {\n    if (v !== undefined) this.shipDate.set(v)\n  }\n  @Input('warehouseName') set warehouseNameAttr(v: string | undefined) {\n    if (v !== undefined) this.warehouseName.set(v)\n  }\n  @Input('warehouseFacility') set warehouseFacilityAttr(v: string | undefined) {\n    if (v !== undefined) this.warehouseFacility.set(v)\n  }\n  @Input('warehouseAddress') set warehouseAddressAttr(v: string | undefined) {\n    if (v !== undefined) this.warehouseAddress.set(v)\n  }\n  @Input('warehousePhone') set warehousePhoneAttr(v: string | undefined) {\n    if (v !== undefined) this.warehousePhone.set(v)\n  }\n  @Input('warehouseEmail') set warehouseEmailAttr(v: string | undefined) {\n    if (v !== undefined) this.warehouseEmail.set(v)\n  }\n  @Input('customerName') set customerNameAttr(v: string | undefined) {\n    if (v !== undefined) this.customerName.set(v)\n  }\n  @Input('customerCompany') set customerCompanyAttr(v: string | undefined) {\n    if (v !== undefined) this.customerCompany.set(v)\n  }\n  @Input('customerAddress') set customerAddressAttr(v: string | undefined) {\n    if (v !== undefined) this.customerAddress.set(v)\n  }\n  @Input('customerPhone') set customerPhoneAttr(v: string | undefined) {\n    if (v !== undefined) this.customerPhone.set(v)\n  }\n  @Input('customerEmail') set customerEmailAttr(v: string | undefined) {\n    if (v !== undefined) this.customerEmail.set(v)\n  }\n  @Input('deliveryNotes') set deliveryNotesAttr(v: string | undefined) {\n    if (v !== undefined) this.deliveryNotes.set(v)\n  }\n  @Input('pickerName') set pickerNameAttr(v: string | undefined) {\n    if (v !== undefined) this.pickerName.set(v)\n  }\n  @Input('pickerId') set pickerIdAttr(v: string | undefined) {\n    if (v !== undefined) this.pickerId.set(v)\n  }\n  @Input('packStation') set packStationAttr(v: string | undefined) {\n    if (v !== undefined) this.packStation.set(v)\n  }\n  @Input('shift') set shiftAttr(v: string | undefined) {\n    if (v !== undefined) this.shift.set(v)\n  }\n  @Input('boxSize') set boxSizeAttr(v: string | undefined) {\n    if (v !== undefined) this.boxSize.set(v)\n  }\n  @Input('dunnageType') set dunnageAttr(v: string | undefined) {\n    if (v !== undefined) this.dunnageType.set(v)\n  }\n  @Input('qcInspector') set qcInspectorAttr(v: string | undefined) {\n    if (v !== undefined) this.qcInspector.set(v)\n  }\n  @Input('qcStamp') set qcStampAttr(v: string | undefined) {\n    if (v !== undefined) this.qcStamp.set(v)\n  }\n  @Input('qcTimestamp') set qcTimestampAttr(v: string | undefined) {\n    if (v !== undefined) this.qcTimestamp.set(v)\n  }\n  @Input('showActions') set showActionsAttr(v: boolean | undefined) {\n    if (v !== undefined) this.showActions.set(!!v)\n  }\n  @Input('initialPackedAll') set initialPackedAllAttr(v: boolean | undefined) {\n    if (v !== undefined) {\n      this.initialPackedAll.set(!!v)\n      this.packedState.set(buildPackedMap(this.effectiveItems(), !!v))\n    }\n  }\n  @Input('items') set itemsAttr(v: PackingSlipItem[] | undefined) {\n    if (v !== undefined) {\n      this.itemsInput.set([...v])\n      this.packedState.set(buildPackedMap(v, this.initialPackedAll()))\n    }\n  }\n  @Input('class') className?: string\n\n  readonly packedState = signal<Record<string, boolean>>(buildPackedMap(defaultItems, false))\n  readonly copiedTracking = signal(false)\n  readonly isPrinting = signal(false)\n  readonly isDownloading = signal(false)\n\n  readonly effectiveItems = computed(() => this.itemsInput() ?? defaultItems)\n\n  readonly totalOrderedUnits = computed(() => this.effectiveItems().reduce((sum, item) => sum + item.qtyOrdered, 0))\n  readonly totalPackedUnits = computed(() =>\n    this.effectiveItems().reduce((sum, item) => sum + (this.packedState()[item.id] ? item.qtyPacked : 0), 0),\n  )\n  readonly totalWeight = computed(() => this.effectiveItems().reduce((sum, item) => sum + item.weightLbs, 0))\n  readonly totalWeightLabel = computed(() => `${this.totalWeight().toFixed(1)} lbs`)\n  readonly isAllPacked = computed(() => this.effectiveItems().every((item) => this.packedState()[item.id]))\n  readonly verifiedItemsCount = computed(\n    () => this.effectiveItems().filter((item) => this.packedState()[item.id]).length,\n  )\n  readonly progressPercentage = computed(() => {\n    if (this.effectiveItems().length === 0) return 0\n    return Math.round((this.verifiedItemsCount() / this.effectiveItems().length) * 100)\n  })\n  readonly barcodeRef = computed(() => this.orderNo().replace('#', ''))\n\n  get rootClass(): string {\n    return cn('w-full space-y-6', this.className)\n  }\n\n  rowClass(id: string): string {\n    return cn(\n      'cursor-pointer transition-colors select-none',\n      this.packedState()[id] ? 'bg-primary/[0.02] dark:bg-primary/[0.04]' : 'hover:bg-muted/20',\n    )\n  }\n\n  itemNameClass(id: string): string {\n    return cn('text-foreground text-xs font-semibold', this.packedState()[id] && 'text-foreground/90')\n  }\n\n  toggleItemPacked(id: string): void {\n    this.packedState.update((prev) => ({ ...prev, [id]: !prev[id] }))\n  }\n\n  setItemPacked(id: string, value: boolean | 'indeterminate'): void {\n    this.packedState.update((prev) => ({ ...prev, [id]: value === true }))\n  }\n\n  markAllPacked(): void {\n    const next: Record<string, boolean> = {}\n    for (const item of this.effectiveItems()) next[item.id] = true\n    this.packedState.set(next)\n  }\n\n  resetPackingChecklist(): void {\n    const next: Record<string, boolean> = {}\n    for (const item of this.effectiveItems()) next[item.id] = false\n    this.packedState.set(next)\n  }\n\n  async copyTrackingNumber(): Promise<void> {\n    try {\n      await navigator.clipboard.writeText(this.trackingNo())\n      this.copiedTracking.set(true)\n      setTimeout(() => this.copiedTracking.set(false), 2000)\n    } catch {\n      // Clipboard unavailable (non-secure context): leave the icon unchanged.\n    }\n  }\n\n  handlePrint(): void {\n    this.isPrinting.set(true)\n    if (typeof window !== 'undefined') window.print()\n    setTimeout(() => this.isPrinting.set(false), 1000)\n  }\n\n  handleDownloadPdf(): void {\n    this.isDownloading.set(true)\n    setTimeout(() => this.isDownloading.set(false), 1500)\n  }\n}\n",
      "type": "registry:block",
      "target": "~/src/app/components/blocks/packing-slip-generator/packing-slip-generator.component.ts"
    },
    {
      "path": "packages/registry-angular/blocks/packing-slip-generator/index.ts",
      "content": "export {\n  UiPackingSlipGeneratorComponent,\n  type PackingSlipItem,\n  type PackingSlipGeneratorInputs,\n} from './packing-slip-generator.component'\n",
      "type": "registry:block",
      "target": "~/src/app/components/blocks/packing-slip-generator/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/checkbox.json",
    "https://uipkge.dev/r/angular/separator.json",
    "https://uipkge.dev/r/angular/table.json"
  ],
  "description": "Shopify and ShipStation style warehouse order packing slip and picker verification checklist with warehouse header, customer ship-to routing, picker pack station barcode scan identifier, itemized pick list table with interactive packed checkboxes, bin location tags, SKU barcodes, weight calculations, and quality control inspector stamp.",
  "categories": [
    "logistics",
    "app",
    "ecommerce",
    "documents"
  ]
}