{
  "$schema": "https://uipkge.dev/schema/registry-item.json",
  "name": "order-management-page",
  "title": "Order Management Page",
  "type": "registry:page",
  "files": [
    {
      "path": "packages/registry-angular/blocks/order-management-page/order-management-page.component.ts",
      "content": "// E-commerce and SaaS order fulfillment admin table: header actions, 4 KPI cards,\n// search + status filter toolbar, selectable rows with avatars and status badges,\n// slide-over order details drawer, bulk action bar, and pagination. Port of the\n// Vue/React block 1:1.\nimport { ChangeDetectionStrategy, Component, Input, computed, signal } from '@angular/core'\nimport {\n  ArrowUpRight,\n  Calendar,\n  ChevronDown,\n  Clock,\n  DollarSign,\n  Download,\n  Eye,\n  FileText,\n  LucideAngularModule,\n  MoreHorizontal,\n  PackageCheck,\n  Plus,\n  RotateCcw,\n  Search,\n  ShoppingCart,\n  TrendingUp,\n  Truck,\n} from 'lucide-angular'\nimport { cn } from '@/lib/utils'\nimport { UiAvatarComponent, UiAvatarFallbackComponent } from '@/ui/avatar/avatar.component'\nimport { UiBadgeComponent } from '@/ui/badge/badge.component'\nimport { UiButtonComponent } from '@/ui/button/button.component'\nimport { UiCardComponent, UiCardContentComponent } from '@/ui/card/card.component'\nimport { UiCheckboxComponent } from '@/ui/checkbox/checkbox.component'\nimport {\n  UiDropdownMenuComponent,\n  UiDropdownMenuContentComponent,\n  UiDropdownMenuItemComponent,\n  UiDropdownMenuLabelComponent,\n  UiDropdownMenuSeparatorComponent,\n  UiDropdownMenuTriggerComponent,\n} from '@/ui/dropdown-menu/dropdown-menu.component'\nimport { UiInputComponent } from '@/ui/input/input.component'\nimport {\n  UiSheetCloseComponent,\n  UiSheetComponent,\n  UiSheetContentComponent,\n  UiSheetDescriptionComponent,\n  UiSheetFooterComponent,\n  UiSheetHeaderComponent,\n  UiSheetTitleComponent,\n} from '@/ui/sheet/sheet.component'\nimport {\n  UiTableBodyComponent,\n  UiTableCellComponent,\n  UiTableComponent,\n  UiTableHeadComponent,\n  UiTableHeaderComponent,\n  UiTableRowComponent,\n} from '@/ui/table/table.component'\n\nexport type OrderStatus = 'paid' | 'processing' | 'shipped' | 'refunded'\n\nexport interface OrderItem {\n  name: string\n  sku: string\n  quantity: number\n  price: number\n}\n\nexport interface CustomerInfo {\n  name: string\n  email: string\n  avatar?: string\n  address: string\n  city: string\n  state: string\n  zip: string\n}\n\nexport interface Order {\n  id: string\n  orderNumber: string\n  date: string\n  customer: CustomerInfo\n  items: OrderItem[]\n  status: OrderStatus\n  paymentMethod: string\n  subtotal: number\n  shipping: number\n  tax: number\n  total: number\n  carrier?: string\n  trackingNumber?: string\n}\n\nexport const orders: Order[] = [\n  {\n    id: 'ord-1',\n    orderNumber: '#ORD-8492',\n    date: 'Oct 24, 2026',\n    customer: {\n      name: 'Sarah Chen',\n      email: 'sarah.chen@example.com',\n      address: '742 Evergreen Terrace',\n      city: 'Springfield',\n      state: 'OR',\n      zip: '97477',\n    },\n    items: [\n      { name: 'Ergonomic Mechanical Keyboard', sku: 'KB-ERGO-01', quantity: 1, price: 189 },\n      { name: 'Desk Mat Pro (Midnight)', sku: 'MAT-PRO-BLK', quantity: 1, price: 39 },\n    ],\n    status: 'processing',\n    paymentMethod: 'Mastercard •••• 8492',\n    subtotal: 228,\n    shipping: 0,\n    tax: 18.24,\n    total: 246.24,\n    carrier: 'FedEx Priority',\n    trackingNumber: 'FX-9281034-US',\n  },\n  {\n    id: 'ord-2',\n    orderNumber: '#ORD-8491',\n    date: 'Oct 24, 2026',\n    customer: {\n      name: 'Marcus Vance',\n      email: 'marcus.v@acme-corp.com',\n      address: '100 Enterprise Way, Suite 400',\n      city: 'San Francisco',\n      state: 'CA',\n      zip: '94105',\n    },\n    items: [\n      { name: 'UltraWide Monitor 34\"', sku: 'MON-34-UW', quantity: 1, price: 699 },\n      { name: 'Dual Monitor Arm Mount', sku: 'ACC-ARM-02', quantity: 1, price: 129 },\n      { name: 'Braided DisplayPort Cable 2m', sku: 'CAB-DP-02', quantity: 1, price: 24 },\n    ],\n    status: 'shipped',\n    paymentMethod: 'Visa •••• 4242',\n    subtotal: 852,\n    shipping: 0,\n    tax: 68.16,\n    total: 920.16,\n    carrier: 'UPS Ground',\n    trackingNumber: '1Z999AA10123456784',\n  },\n  {\n    id: 'ord-3',\n    orderNumber: '#ORD-8490',\n    date: 'Oct 23, 2026',\n    customer: {\n      name: 'Elena Rostova',\n      email: 'elena.rostova@techflow.io',\n      address: '450 Innovation Parkway',\n      city: 'Austin',\n      state: 'TX',\n      zip: '78701',\n    },\n    items: [{ name: 'SaaS Enterprise Annual License', sku: 'LIC-ENT-YR', quantity: 1, price: 1200 }],\n    status: 'paid',\n    paymentMethod: 'Visa •••• 9104',\n    subtotal: 1200,\n    shipping: 0,\n    tax: 0,\n    total: 1200,\n  },\n  {\n    id: 'ord-4',\n    orderNumber: '#ORD-8489',\n    date: 'Oct 23, 2026',\n    customer: {\n      name: 'David Kim',\n      email: 'david.kim@designly.co',\n      address: '88 King Street West',\n      city: 'Seattle',\n      state: 'WA',\n      zip: '98104',\n    },\n    items: [\n      { name: 'USB-C Multiport Dock Pro', sku: 'HUB-USBC-8P', quantity: 2, price: 79 },\n      { name: 'Thunderbolt 4 Braided Cable', sku: 'CAB-TB4-1M', quantity: 2, price: 29 },\n    ],\n    status: 'shipped',\n    paymentMethod: 'Apple Pay',\n    subtotal: 216,\n    shipping: 0,\n    tax: 17.28,\n    total: 233.28,\n    carrier: 'DHL Express',\n    trackingNumber: 'DHL-8492019-EXP',\n  },\n  {\n    id: 'ord-5',\n    orderNumber: '#ORD-8488',\n    date: 'Oct 22, 2026',\n    customer: {\n      name: 'Olivia Taylor',\n      email: 'olivia.t@summit.ai',\n      address: '12 Marina Boulevard',\n      city: 'Boston',\n      state: 'MA',\n      zip: '02210',\n    },\n    items: [{ name: 'Noise-Cancelling Studio Headphones', sku: 'AUD-NC-700', quantity: 1, price: 349 }],\n    status: 'refunded',\n    paymentMethod: 'Visa •••• 1128',\n    subtotal: 349,\n    shipping: 0,\n    tax: 27.92,\n    total: 376.92,\n  },\n  {\n    id: 'ord-6',\n    orderNumber: '#ORD-8487',\n    date: 'Oct 22, 2026',\n    customer: {\n      name: 'Liam Johansson',\n      email: 'liam.j@nordic.se',\n      address: '240 Queen Street',\n      city: 'New York',\n      state: 'NY',\n      zip: '10001',\n    },\n    items: [\n      { name: 'Aluminum Laptop Riser', sku: 'STN-ALUM-SLV', quantity: 1, price: 65 },\n      { name: 'Wireless Precision Mouse', sku: 'MOU-WL-01', quantity: 1, price: 99 },\n    ],\n    status: 'processing',\n    paymentMethod: 'Mastercard •••• 5531',\n    subtotal: 164,\n    shipping: 0,\n    tax: 13.12,\n    total: 177.12,\n    carrier: 'USPS Priority',\n    trackingNumber: '9400100000000000000000',\n  },\n  {\n    id: 'ord-7',\n    orderNumber: '#ORD-8486',\n    date: 'Oct 21, 2026',\n    customer: {\n      name: 'Aisha Patel',\n      email: 'aisha.patel@globalnet.com',\n      address: '500 Central Avenue',\n      city: 'Chicago',\n      state: 'IL',\n      zip: '60601',\n    },\n    items: [{ name: 'Cloud Storage Tier 3 (500GB)', sku: 'SRV-STR-500', quantity: 1, price: 450 }],\n    status: 'paid',\n    paymentMethod: 'Amex •••• 3009',\n    subtotal: 450,\n    shipping: 0,\n    tax: 36,\n    total: 486,\n  },\n  {\n    id: 'ord-8',\n    orderNumber: '#ORD-8485',\n    date: 'Oct 20, 2026',\n    customer: {\n      name: 'Lucas Moreau',\n      email: 'lucas.m@atelier.fr',\n      address: '15 Rue de la Paix',\n      city: 'Boulder',\n      state: 'CO',\n      zip: '80302',\n    },\n    items: [\n      { name: 'Broadcast Studio Microphone', sku: 'MIC-POD-01', quantity: 1, price: 229 },\n      { name: 'Dual-Layer Pop Filter', sku: 'ACC-POP-01', quantity: 1, price: 25 },\n      { name: 'Gold-Plated XLR Cable 3m', sku: 'CAB-XLR-03', quantity: 1, price: 19 },\n    ],\n    status: 'shipped',\n    paymentMethod: 'Visa •••• 7712',\n    subtotal: 273,\n    shipping: 0,\n    tax: 21.84,\n    total: 294.84,\n    carrier: 'FedEx Ground',\n    trackingNumber: 'FX-7712093-US',\n  },\n]\n\nconst statusBadgeConfig: Record<OrderStatus, { label: string; class: string; dot: string }> = {\n  paid: { label: 'Paid', class: 'bg-success/10 text-success border-success/20', dot: 'bg-success' },\n  processing: { label: 'Processing', class: 'bg-info/10 text-info border-info/20', dot: 'bg-info' },\n  shipped: { label: 'Shipped', class: 'bg-chart-1/10 text-chart-1 border-chart-1/20', dot: 'bg-chart-1' },\n  refunded: {\n    label: 'Refunded',\n    class: 'bg-destructive/10 text-destructive border-destructive/20',\n    dot: 'bg-destructive',\n  },\n}\n\n@Component({\n  changeDetection: ChangeDetectionStrategy.Eager,\n  selector: 'ui-order-management-page, [ui-order-management-page]',\n  standalone: true,\n  // The block renders its own root <div> (and the sheet portals to body): keep the host out of layout.\n  host: { '[attr.class]': '\"contents\"' },\n  imports: [\n    LucideAngularModule,\n    UiAvatarComponent,\n    UiAvatarFallbackComponent,\n    UiBadgeComponent,\n    UiButtonComponent,\n    UiCardComponent,\n    UiCardContentComponent,\n    UiCheckboxComponent,\n    UiDropdownMenuComponent,\n    UiDropdownMenuContentComponent,\n    UiDropdownMenuItemComponent,\n    UiDropdownMenuLabelComponent,\n    UiDropdownMenuSeparatorComponent,\n    UiDropdownMenuTriggerComponent,\n    UiInputComponent,\n    UiSheetCloseComponent,\n    UiSheetComponent,\n    UiSheetContentComponent,\n    UiSheetDescriptionComponent,\n    UiSheetFooterComponent,\n    UiSheetHeaderComponent,\n    UiSheetTitleComponent,\n    UiTableBodyComponent,\n    UiTableCellComponent,\n    UiTableComponent,\n    UiTableHeadComponent,\n    UiTableHeaderComponent,\n    UiTableRowComponent,\n  ],\n  template: `\n    <div data-slot=\"order-management-page\" [class]=\"rootClass\">\n      <!-- Page Header -->\n      <div class=\"flex flex-wrap items-center justify-between gap-4\">\n        <div>\n          <h2 class=\"text-foreground text-2xl font-bold tracking-tight\">Orders</h2>\n          <p class=\"text-muted-foreground mt-1 text-sm\">Manage and track customer purchases</p>\n        </div>\n        <div class=\"flex items-center gap-2\">\n          <button ui-button aria-label=\"Download attachment\" variant=\"outline\" size=\"sm\" class=\"text-xs\">\n            <lucide-icon [img]=\"Download\" class=\"mr-1.5 size-3.5\" aria-hidden=\"true\" />\n            Export CSV\n          </button>\n          <button ui-button size=\"sm\" class=\"text-xs\">\n            <lucide-icon [img]=\"Plus\" class=\"mr-1.5 size-3.5\" aria-hidden=\"true\" />\n            New Order\n          </button>\n        </div>\n      </div>\n\n      <!-- 4 Stat/KPI Summary Cards -->\n      <div class=\"grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4\">\n        <div ui-card class=\"shadow-xs\">\n          <div ui-card-content class=\"p-4 sm:p-5\">\n            <div class=\"flex items-center justify-between\">\n              <p class=\"text-muted-foreground text-xs font-medium tracking-wider uppercase\">Total Orders</p>\n              <div class=\"bg-muted text-muted-foreground flex size-8 items-center justify-center rounded-md\">\n                <lucide-icon [img]=\"ShoppingCart\" class=\"size-4\" aria-hidden=\"true\" />\n              </div>\n            </div>\n            <div class=\"mt-3 flex flex-wrap items-baseline justify-between gap-2\">\n              <span class=\"text-foreground text-2xl font-bold tracking-tight tabular-nums\">1,429</span>\n              <span class=\"text-success inline-flex items-center gap-0.5 text-xs font-medium\">\n                <lucide-icon [img]=\"TrendingUp\" class=\"size-3.5\" aria-hidden=\"true\" />\n                +8.2%\n              </span>\n            </div>\n            <p class=\"text-muted-foreground mt-1 text-xs\">vs. previous 30 days</p>\n          </div>\n        </div>\n\n        <div ui-card class=\"shadow-xs\">\n          <div ui-card-content class=\"p-4 sm:p-5\">\n            <div class=\"flex items-center justify-between\">\n              <p class=\"text-muted-foreground text-xs font-medium tracking-wider uppercase\">Pending Fulfillment</p>\n              <div class=\"bg-warning/10 text-warning flex size-8 items-center justify-center rounded-md\">\n                <lucide-icon [img]=\"Clock\" class=\"size-4\" aria-hidden=\"true\" />\n              </div>\n            </div>\n            <div class=\"mt-3 flex flex-wrap items-baseline justify-between gap-2\">\n              <span class=\"text-foreground text-2xl font-bold tracking-tight tabular-nums\">28</span>\n              <span\n                class=\"bg-warning/10 text-warning inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium\"\n              >\n                12 urgent\n              </span>\n            </div>\n            <p class=\"text-muted-foreground mt-1 text-xs\">Requires warehouse dispatch</p>\n          </div>\n        </div>\n\n        <div ui-card class=\"shadow-xs\">\n          <div ui-card-content class=\"p-4 sm:p-5\">\n            <div class=\"flex items-center justify-between\">\n              <p class=\"text-muted-foreground text-xs font-medium tracking-wider uppercase\">Processing</p>\n              <div class=\"bg-info/10 text-info flex size-8 items-center justify-center rounded-md\">\n                <lucide-icon [img]=\"PackageCheck\" class=\"size-4\" aria-hidden=\"true\" />\n              </div>\n            </div>\n            <div class=\"mt-3 flex flex-wrap items-baseline justify-between gap-2\">\n              <span class=\"text-foreground text-2xl font-bold tracking-tight tabular-nums\">45</span>\n              <span class=\"bg-info/10 text-info inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium\">\n                In queue\n              </span>\n            </div>\n            <p class=\"text-muted-foreground mt-1 text-xs\">Packaging & label generation</p>\n          </div>\n        </div>\n\n        <div ui-card class=\"shadow-xs\">\n          <div ui-card-content class=\"p-4 sm:p-5\">\n            <div class=\"flex items-center justify-between\">\n              <p class=\"text-muted-foreground text-xs font-medium tracking-wider uppercase\">Total Revenue</p>\n              <div class=\"bg-muted text-muted-foreground flex size-8 items-center justify-center rounded-md\">\n                <lucide-icon [img]=\"DollarSign\" class=\"size-4\" aria-hidden=\"true\" />\n              </div>\n            </div>\n            <div class=\"mt-3 flex flex-wrap items-baseline justify-between gap-2\">\n              <span class=\"text-foreground text-2xl font-bold tracking-tight tabular-nums\">$128,450</span>\n              <span class=\"text-success inline-flex items-center gap-0.5 text-xs font-medium\">\n                <lucide-icon [img]=\"ArrowUpRight\" class=\"size-3.5\" aria-hidden=\"true\" />\n                +14.5%\n              </span>\n            </div>\n            <p class=\"text-muted-foreground mt-1 text-xs\">vs. previous period</p>\n          </div>\n        </div>\n      </div>\n\n      <!-- Search and Filter Toolbar -->\n      <div class=\"flex flex-col gap-3 lg:flex-row lg:items-center lg:justify-between\">\n        <div class=\"flex flex-1 flex-wrap items-center gap-2\">\n          <ng-template #orderSearchIcon>\n            <lucide-icon [img]=\"Search\" class=\"size-4\" aria-hidden=\"true\" />\n          </ng-template>\n          <div class=\"relative min-w-[240px] flex-1 sm:max-w-xs\">\n            <ui-input\n              [value]=\"search()\"\n              (valueChange)=\"search.set($event)\"\n              placeholder=\"Search order ID, customer...\"\n              [prefixIcon]=\"orderSearchIcon\"\n              class=\"h-9 pl-2 text-xs\"\n            />\n          </div>\n\n          <div class=\"bg-muted/60 flex items-center gap-1 rounded-lg border p-1\">\n            @for (status of statusOptions(); track status.value) {\n              <button type=\"button\" [class]=\"statusPillClass(status.value)\" (click)=\"setStatusFilter(status.value)\">\n                {{ status.label }}\n                <span [class]=\"statusCountClass(status.value)\">{{ status.count }}</span>\n              </button>\n            }\n          </div>\n        </div>\n\n        <div class=\"flex items-center gap-2\">\n          <button ui-button variant=\"outline\" size=\"sm\" class=\"text-xs font-normal\">\n            <lucide-icon [img]=\"Calendar\" class=\"text-muted-foreground mr-1.5 size-3.5\" aria-hidden=\"true\" />\n            Last 30 days\n            <lucide-icon [img]=\"ChevronDown\" class=\"text-muted-foreground ml-1.5 size-3.5\" aria-hidden=\"true\" />\n          </button>\n        </div>\n      </div>\n\n      <!-- Bulk Action Bar -->\n      @if (selected().size > 0) {\n        <div\n          class=\"bg-muted/50 flex flex-wrap items-center justify-between gap-2 rounded-lg border px-4 py-2.5 shadow-xs\"\n        >\n          <div class=\"flex items-center gap-2\">\n            <span\n              class=\"bg-primary text-primary-foreground flex size-5 items-center justify-center rounded-full text-xs font-medium\"\n            >\n              {{ selected().size }}\n            </span>\n            <span class=\"text-foreground text-sm font-medium\">\n              {{ selected().size }} {{ selected().size === 1 ? 'order' : 'orders' }} selected\n            </span>\n          </div>\n          <div class=\"flex items-center gap-2\">\n            <button\n              ui-button\n              aria-label=\"Download attachment\"\n              variant=\"outline\"\n              size=\"sm\"\n              class=\"text-xs\"\n              (click)=\"exportSelected()\"\n            >\n              <lucide-icon [img]=\"Download\" class=\"mr-1.5 size-3.5\" aria-hidden=\"true\" />\n              Export selected\n            </button>\n            <button ui-button variant=\"outline\" size=\"sm\" class=\"text-xs\" (click)=\"markSelectedShipped()\">\n              <lucide-icon [img]=\"Truck\" class=\"mr-1.5 size-3.5\" aria-hidden=\"true\" />\n              Mark as shipped\n            </button>\n            <button\n              ui-button\n              variant=\"ghost\"\n              size=\"sm\"\n              class=\"text-destructive hover:text-destructive text-xs\"\n              (click)=\"clearSelection()\"\n            >\n              Cancel\n            </button>\n          </div>\n        </div>\n      }\n\n      <!-- Orders Table -->\n      <div class=\"bg-card overflow-x-auto rounded-lg border shadow-xs\">\n        <table ui-table>\n          <thead ui-table-header>\n            <tr ui-table-row class=\"hover:bg-transparent\">\n              <th ui-table-head class=\"w-10\">\n                <ui-checkbox\n                  [checked]=\"allSelected()\"\n                  [indeterminate]=\"someSelected() && !allSelected()\"\n                  aria-label=\"Select all orders\"\n                  (checkedChange)=\"toggleAll($event === true)\"\n                />\n              </th>\n              <th ui-table-head class=\"min-w-[110px]\">Order ID</th>\n              <th ui-table-head class=\"min-w-[100px]\">Date</th>\n              <th ui-table-head class=\"min-w-[200px]\">Customer</th>\n              <th ui-table-head class=\"min-w-[220px]\">Items</th>\n              <th ui-table-head class=\"min-w-[90px] text-right\">Total</th>\n              <th ui-table-head class=\"min-w-[120px]\">Fulfillment</th>\n              <th ui-table-head class=\"w-10 text-right\"><span class=\"sr-only\">Actions</span></th>\n            </tr>\n          </thead>\n          <tbody ui-table-body>\n            @for (order of filteredOrders(); track order.id) {\n              <tr\n                ui-table-row\n                class=\"group hover:bg-muted/40 cursor-pointer transition-colors\"\n                (click)=\"openOrderDetails(order)\"\n              >\n                <td ui-table-cell class=\"w-10\" (click)=\"$event.stopPropagation()\">\n                  <ui-checkbox\n                    [checked]=\"selected().has(order.id)\"\n                    [attr.aria-label]=\"'Select order ' + order.orderNumber\"\n                    (checkedChange)=\"toggleRow(order.id, $event === true)\"\n                  />\n                </td>\n                <td ui-table-cell>\n                  <span class=\"text-foreground font-mono text-xs font-semibold hover:underline\">\n                    {{ order.orderNumber }}\n                  </span>\n                </td>\n                <td ui-table-cell class=\"text-muted-foreground text-xs tabular-nums\">{{ order.date }}</td>\n                <td ui-table-cell>\n                  <div class=\"flex items-center gap-2.5\">\n                    <ui-avatar class=\"size-7\">\n                      <ui-avatar-fallback class=\"text-xs font-medium\">{{\n                        initials(order.customer.name)\n                      }}</ui-avatar-fallback>\n                    </ui-avatar>\n                    <div class=\"min-w-0\">\n                      <p class=\"text-foreground truncate text-sm font-medium\">{{ order.customer.name }}</p>\n                      <p class=\"text-muted-foreground truncate text-xs\">{{ order.customer.email }}</p>\n                    </div>\n                  </div>\n                </td>\n                <td ui-table-cell>\n                  <div class=\"text-xs\">\n                    <span class=\"text-foreground font-medium\">\n                      {{ itemCount(order) }} {{ itemCount(order) === 1 ? 'item' : 'items' }}\n                    </span>\n                    <span class=\"text-muted-foreground ml-1.5 inline-block max-w-[180px] truncate align-bottom\">\n                      • {{ order.items[0]?.name\n                      }}{{ order.items.length > 1 ? ' +' + (order.items.length - 1) + ' more' : '' }}\n                    </span>\n                  </div>\n                </td>\n                <td ui-table-cell class=\"text-foreground text-right font-mono text-xs font-semibold tabular-nums\">\n                  &#36;{{ formatCurrency(order.total) }}\n                </td>\n                <td ui-table-cell>\n                  <span ui-badge variant=\"outline\" [class]=\"statusBadgeClass(order.status)\">\n                    <span [class]=\"statusDotClass(order.status)\" aria-hidden=\"true\"></span>\n                    {{ statusBadgeConfig[order.status].label }}\n                  </span>\n                </td>\n                <td ui-table-cell class=\"text-right\" (click)=\"$event.stopPropagation()\">\n                  <ui-dropdown-menu>\n                    <button\n                      ui-button\n                      ui-dropdown-menu-trigger\n                      variant=\"ghost\"\n                      size=\"icon-sm\"\n                      class=\"text-muted-foreground hover:text-foreground\"\n                    >\n                      <lucide-icon [img]=\"MoreHorizontal\" class=\"size-4\" aria-hidden=\"true\" />\n                      <span class=\"sr-only\">Actions for {{ order.orderNumber }}</span>\n                    </button>\n                    <ui-dropdown-menu-content align=\"end\" class=\"w-48\">\n                      <ui-dropdown-menu-label>Order actions</ui-dropdown-menu-label>\n                      <ui-dropdown-menu-item (select)=\"openOrderDetails(order)\">\n                        <lucide-icon [img]=\"Eye\" class=\"mr-2 size-4\" aria-hidden=\"true\" />\n                        View details\n                      </ui-dropdown-menu-item>\n                      <ui-dropdown-menu-item>\n                        <lucide-icon [img]=\"FileText\" class=\"mr-2 size-4\" aria-hidden=\"true\" />\n                        Download invoice\n                      </ui-dropdown-menu-item>\n                      @if (order.status === 'processing') {\n                        <ui-dropdown-menu-item>\n                          <lucide-icon [img]=\"Truck\" class=\"mr-2 size-4\" aria-hidden=\"true\" />\n                          Mark as shipped\n                        </ui-dropdown-menu-item>\n                      }\n                      <ui-dropdown-menu-separator />\n                      @if (order.status !== 'refunded') {\n                        <ui-dropdown-menu-item class=\"text-destructive focus:text-destructive\">\n                          <lucide-icon [img]=\"RotateCcw\" class=\"mr-2 size-4\" aria-hidden=\"true\" />\n                          Issue refund\n                        </ui-dropdown-menu-item>\n                      }\n                    </ui-dropdown-menu-content>\n                  </ui-dropdown-menu>\n                </td>\n              </tr>\n            }\n            @if (filteredOrders().length === 0) {\n              <tr ui-table-row>\n                <td ui-table-cell colspan=\"8\" class=\"text-muted-foreground h-32 text-center text-sm\">\n                  No orders match your filter criteria.\n                </td>\n              </tr>\n            }\n          </tbody>\n        </table>\n      </div>\n\n      <!-- Pagination Footer -->\n      <div class=\"flex flex-wrap items-center justify-between gap-4\">\n        <p class=\"text-muted-foreground text-xs tabular-nums\">\n          Showing 1-{{ filteredOrders().length }} of 1,429 orders\n        </p>\n        <div class=\"flex items-center gap-2\">\n          <button ui-button variant=\"outline\" size=\"sm\" class=\"text-xs\" disabled>Previous</button>\n          <button ui-button variant=\"outline\" size=\"sm\" class=\"text-xs\">Next</button>\n        </div>\n      </div>\n\n      <!-- Quick Details Drawer / Sheet -->\n      <div ui-sheet [open]=\"drawerOpen()\" (openChange)=\"drawerOpen.set($event)\">\n        <div ui-sheet-content side=\"right\" class=\"flex w-full flex-col gap-0 overflow-y-auto p-0 sm:max-w-lg\">\n          @if (selectedOrder(); as detail) {\n            <div class=\"flex h-full flex-col\">\n              <!-- Sheet Header -->\n              <div ui-sheet-header class=\"space-y-1 border-b px-6 py-5\">\n                <div class=\"flex items-center justify-between pr-6\">\n                  <span class=\"text-foreground font-mono text-base font-bold\">{{ detail.orderNumber }}</span>\n                  <span ui-badge variant=\"outline\" [class]=\"statusBadgeDrawerClass(detail.status)\">\n                    <span [class]=\"statusDotClass(detail.status)\" aria-hidden=\"true\"></span>\n                    {{ statusBadgeConfig[detail.status].label }}\n                  </span>\n                </div>\n                <h2 ui-sheet-title class=\"text-muted-foreground text-xs font-normal\">Placed on {{ detail.date }}</h2>\n                <p ui-sheet-description class=\"sr-only\">Detailed view of order {{ detail.orderNumber }}</p>\n              </div>\n\n              <!-- Sheet Body -->\n              <div class=\"flex-1 space-y-6 overflow-y-auto px-6 py-5 text-sm\">\n                <!-- Customer & Shipping -->\n                <div class=\"bg-muted/20 space-y-3 rounded-lg border p-4\">\n                  <div class=\"flex items-center justify-between\">\n                    <h4 class=\"text-muted-foreground text-xs font-semibold tracking-wider uppercase\">\n                      Customer & Shipping\n                    </h4>\n                    <span class=\"text-muted-foreground font-mono text-xs\">{{ detail.paymentMethod }}</span>\n                  </div>\n                  <div class=\"flex items-center gap-3\">\n                    <ui-avatar class=\"size-9\">\n                      <ui-avatar-fallback class=\"text-xs font-semibold\">\n                        {{ initials(detail.customer.name) }}\n                      </ui-avatar-fallback>\n                    </ui-avatar>\n                    <div class=\"min-w-0\">\n                      <p class=\"text-foreground font-medium\">{{ detail.customer.name }}</p>\n                      <p class=\"text-muted-foreground text-xs\">{{ detail.customer.email }}</p>\n                    </div>\n                  </div>\n                  <div class=\"text-muted-foreground border-t pt-2.5 text-xs\">\n                    <p class=\"text-foreground font-medium\">Delivery address:</p>\n                    <p>{{ detail.customer.address }}</p>\n                    <p>{{ detail.customer.city }}, {{ detail.customer.state }} {{ detail.customer.zip }}</p>\n                  </div>\n                </div>\n\n                <!-- Fulfillment & Tracking if available -->\n                @if (detail.carrier && detail.trackingNumber) {\n                  <div class=\"border-border bg-card space-y-2 rounded-lg border p-4\">\n                    <div class=\"flex items-center justify-between\">\n                      <span class=\"text-muted-foreground text-xs font-semibold tracking-wider uppercase\"\n                        >Fulfillment</span\n                      >\n                      <span ui-badge variant=\"secondary\" class=\"text-xs font-normal\">In Transit</span>\n                    </div>\n                    <div class=\"flex items-center justify-between pt-1 text-xs\">\n                      <span class=\"text-muted-foreground\">Carrier:</span>\n                      <span class=\"text-foreground font-medium\">{{ detail.carrier }}</span>\n                    </div>\n                    <div class=\"flex items-center justify-between text-xs\">\n                      <span class=\"text-muted-foreground\">Tracking ID:</span>\n                      <span class=\"text-foreground font-mono font-medium\">{{ detail.trackingNumber }}</span>\n                    </div>\n                  </div>\n                }\n\n                <!-- Line Items -->\n                <div class=\"space-y-3\">\n                  <h4 class=\"text-muted-foreground text-xs font-semibold tracking-wider uppercase\">Line Items</h4>\n                  <div class=\"divide-border bg-card divide-y rounded-lg border\">\n                    @for (item of detail.items; track item.sku) {\n                      <div class=\"flex items-center justify-between gap-3 p-3.5\">\n                        <div class=\"min-w-0 flex-1\">\n                          <p class=\"text-foreground truncate text-sm font-medium\">{{ item.name }}</p>\n                          <p class=\"text-muted-foreground font-mono text-xs\">\n                            SKU: {{ item.sku }} • Qty: {{ item.quantity }} × &#36;{{ formatCurrency(item.price) }}\n                          </p>\n                        </div>\n                        <div class=\"text-foreground font-mono text-xs font-semibold tabular-nums\">\n                          &#36;{{ formatCurrency(item.price * item.quantity) }}\n                        </div>\n                      </div>\n                    }\n                  </div>\n                </div>\n\n                <!-- Cost Breakdown -->\n                <div class=\"bg-card space-y-2 rounded-lg border p-4 text-xs\">\n                  <div class=\"text-muted-foreground flex justify-between\">\n                    <span>Subtotal</span>\n                    <span class=\"text-foreground font-mono tabular-nums\"\n                      >&#36;{{ formatCurrency(detail.subtotal) }}</span\n                    >\n                  </div>\n                  <div class=\"text-muted-foreground flex justify-between\">\n                    <span>Estimated Shipping</span>\n                    <span class=\"text-foreground font-mono tabular-nums\">\n                      {{ detail.shipping === 0 ? 'Free' : '&#36;' + formatCurrency(detail.shipping) }}\n                    </span>\n                  </div>\n                  <div class=\"text-muted-foreground flex justify-between\">\n                    <span>Tax</span>\n                    <span class=\"text-foreground font-mono tabular-nums\">&#36;{{ formatCurrency(detail.tax) }}</span>\n                  </div>\n                  <div class=\"text-foreground flex justify-between border-t pt-2 text-sm font-medium\">\n                    <span>Total</span>\n                    <span class=\"text-foreground font-mono font-bold tabular-nums\">\n                      &#36;{{ formatCurrency(detail.total) }}\n                    </span>\n                  </div>\n                </div>\n              </div>\n\n              <!-- Sheet Footer -->\n              <div\n                ui-sheet-footer\n                class=\"bg-muted/10 flex flex-row items-center justify-between gap-2 border-t px-6 py-4\"\n              >\n                <button ui-button aria-label=\"Download attachment\" variant=\"outline\" size=\"sm\" class=\"text-xs\">\n                  <lucide-icon [img]=\"Download\" class=\"mr-1.5 size-3.5\" aria-hidden=\"true\" />\n                  Invoice PDF\n                </button>\n                <button ui-button ui-sheet-close variant=\"secondary\" size=\"sm\" class=\"text-xs\">Close</button>\n              </div>\n            </div>\n          }\n        </div>\n      </div>\n    </div>\n  `,\n})\nexport class UiOrderManagementPageComponent {\n  protected readonly ArrowUpRight = ArrowUpRight\n  protected readonly Calendar = Calendar\n  protected readonly ChevronDown = ChevronDown\n  protected readonly Clock = Clock\n  protected readonly DollarSign = DollarSign\n  protected readonly Download = Download\n  protected readonly Eye = Eye\n  protected readonly FileText = FileText\n  protected readonly MoreHorizontal = MoreHorizontal\n  protected readonly PackageCheck = PackageCheck\n  protected readonly Plus = Plus\n  protected readonly RotateCcw = RotateCcw\n  protected readonly Search = Search\n  protected readonly ShoppingCart = ShoppingCart\n  protected readonly TrendingUp = TrendingUp\n  protected readonly Truck = Truck\n\n  protected readonly statusBadgeConfig = statusBadgeConfig\n\n  @Input('class') className?: string\n\n  readonly search = signal('')\n  readonly statusFilter = signal<'all' | OrderStatus>('all')\n  readonly selected = signal<Set<string>>(new Set())\n  readonly selectedOrder = signal<Order | null>(null)\n  readonly drawerOpen = signal(false)\n\n  readonly filteredOrders = computed(() => {\n    const query = this.search().trim().toLowerCase()\n    return orders.filter((order) => {\n      const matchesStatus = this.statusFilter() === 'all' || order.status === this.statusFilter()\n      const matchesQuery =\n        !query ||\n        order.orderNumber.toLowerCase().includes(query) ||\n        order.customer.name.toLowerCase().includes(query) ||\n        order.customer.email.toLowerCase().includes(query)\n      return matchesStatus && matchesQuery\n    })\n  })\n\n  readonly statusCounts = computed(() => {\n    const counts: Record<string, number> = { all: orders.length, paid: 0, processing: 0, shipped: 0, refunded: 0 }\n    for (const ord of orders) counts[ord.status] = (counts[ord.status] ?? 0) + 1\n    return counts\n  })\n\n  readonly statusOptions = computed(() => [\n    { value: 'all', label: 'All', count: this.statusCounts().all },\n    { value: 'paid', label: 'Paid', count: this.statusCounts().paid },\n    { value: 'processing', label: 'Processing', count: this.statusCounts().processing },\n    { value: 'shipped', label: 'Shipped', count: this.statusCounts().shipped },\n    { value: 'refunded', label: 'Refunded', count: this.statusCounts().refunded },\n  ])\n\n  readonly allSelected = computed(\n    () => this.filteredOrders().length > 0 && this.filteredOrders().every((ord) => this.selected().has(ord.id)),\n  )\n  readonly someSelected = computed(() => this.filteredOrders().some((ord) => this.selected().has(ord.id)))\n\n  get rootClass(): string {\n    return cn('w-full space-y-6', this.className)\n  }\n\n  statusPillClass(value: string): string {\n    return cn(\n      'rounded-md px-2.5 py-1 text-xs font-medium transition-colors',\n      this.statusFilter() === value\n        ? 'bg-background text-foreground shadow-xs'\n        : 'text-muted-foreground hover:text-foreground',\n    )\n  }\n\n  statusCountClass(value: string): string {\n    return cn(\n      'ml-1.5 rounded-full px-1.5 py-0.5 text-xs font-normal tabular-nums',\n      this.statusFilter() === value ? 'bg-muted text-foreground' : 'text-muted-foreground',\n    )\n  }\n\n  statusBadgeClass(status: OrderStatus): string {\n    return cn('gap-1.5 px-2 py-0.5 text-xs font-medium capitalize', statusBadgeConfig[status].class)\n  }\n\n  statusBadgeDrawerClass(status: OrderStatus): string {\n    return cn('gap-1.5 px-2.5 py-0.5 text-xs font-medium capitalize', statusBadgeConfig[status].class)\n  }\n\n  statusDotClass(status: OrderStatus): string {\n    return cn('size-1.5 rounded-full', statusBadgeConfig[status].dot)\n  }\n\n  setStatusFilter(value: string): void {\n    this.statusFilter.set(value as 'all' | OrderStatus)\n  }\n\n  itemCount(order: Order): number {\n    return order.items.reduce((acc, item) => acc + item.quantity, 0)\n  }\n\n  toggleAll(checked: boolean): void {\n    this.selected.set(checked ? new Set(this.filteredOrders().map((ord) => ord.id)) : new Set())\n  }\n\n  toggleRow(id: string, checked: boolean): void {\n    const next = new Set(this.selected())\n    if (checked) next.add(id)\n    else next.delete(id)\n    this.selected.set(next)\n  }\n\n  clearSelection(): void {\n    this.selected.set(new Set())\n  }\n\n  exportSelected(): void {\n    this.clearSelection()\n  }\n\n  markSelectedShipped(): void {\n    this.clearSelection()\n  }\n\n  openOrderDetails(order: Order): void {\n    this.selectedOrder.set(order)\n    this.drawerOpen.set(true)\n  }\n\n  formatCurrency(val: number): string {\n    return val.toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 })\n  }\n\n  initials(name: string): string {\n    return name\n      .split(' ')\n      .map((p) => p[0])\n      .slice(0, 2)\n      .join('')\n      .toUpperCase()\n  }\n}\n",
      "type": "registry:page",
      "target": "~/src/app/components/blocks/order-management-page/order-management-page.component.ts"
    },
    {
      "path": "packages/registry-angular/blocks/order-management-page/index.ts",
      "content": "export {\n  UiOrderManagementPageComponent,\n  type OrderStatus,\n  type OrderItem,\n  type CustomerInfo,\n  type Order,\n  orders,\n} from './order-management-page.component'\n",
      "type": "registry:page",
      "target": "~/src/app/components/blocks/order-management-page/index.ts"
    }
  ],
  "dependencies": [
    "lucide-angular"
  ],
  "devDependencies": [],
  "registryDependencies": [
    "https://uipkge.dev/r/angular/avatar.json",
    "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/dropdown-menu.json",
    "https://uipkge.dev/r/angular/input.json",
    "https://uipkge.dev/r/angular/sheet.json",
    "https://uipkge.dev/r/angular/table.json"
  ],
  "description": "E-commerce and SaaS order fulfillment admin table: header with export CSV and new order action, 4 KPI summary metric cards, search and multi-status filter toolbar with date range selector, selectable order rows with customer avatars and status badges, slide-over order details drawer with line items breakdown and tracking info, bulk action bar, and pagination.",
  "categories": [
    "commerce",
    "app",
    "ecommerce"
  ]
}