{
  "$schema": "https://uipkge.dev/schema/registry-item.json",
  "name": "order-management-page",
  "title": "Order Management Page",
  "type": "registry:page",
  "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"
  ],
  "files": [
    {
      "path": "packages/elements-lit/src/blocks/order-management-page/order-management-page.ts",
      "content": "import { LitElement, css, html, nothing } from 'lit'\nimport {\n  ArrowUpRight,\n  Calendar,\n  ChevronDown,\n  Clock,\n  DollarSign,\n  Download,\n  Eye,\n  FileText,\n  MoreHorizontal,\n  PackageCheck,\n  Plus,\n  RotateCcw,\n  Search,\n  ShoppingCart,\n  TrendingUp,\n  Truck,\n} from 'lucide'\nimport { cn } from '../../lib/utils'\nimport { tailwind } from '../../lib/styles'\nimport { ThemeController } from '../../lib/theme'\nimport { icon } from '../../lib/icon'\n// Side-effect imports: register the composed elements for standalone use\n// (consumers who install only this block still get working primitives).\nimport '../../components/avatar/avatar'\nimport '../../components/badge/badge'\nimport '../../components/button/button'\nimport '../../components/card/card'\nimport '../../components/checkbox/checkbox'\nimport '../../components/dropdown-menu/dropdown-menu'\nimport '../../components/input/input'\nimport type { UipInput } from '../../components/input/input'\nimport '../../components/sheet/sheet'\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\nconst 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: { label: 'Refunded', class: 'bg-destructive/10 text-destructive border-destructive/20', dot: 'bg-destructive' },\n}\n\nfunction formatCurrency(val: number) {\n  return val.toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 })\n}\n\nfunction initials(name: string) {\n  return name\n    .split(' ')\n    .map((p) => p[0])\n    .slice(0, 2)\n    .join('')\n    .toUpperCase()\n}\n\n/**\n * <uip-order-management-page> — the registry OrderManagementPage block as a web component.\n *\n * Class strings and order data are React's verbatim. React state becomes\n * { state: true } fields. The block takes no props and fires no events; search,\n * status filter, bulk selection, and the details sheet are internal.\n *\n * Two deliberate departures: (1) the orders grid uses a native <table> with\n * the registry Table part classes copied verbatim — <uip-table>'s data-driven\n * API can't express per-row/per-cell custom classes, badges, or row clicks;\n * (2) the search icon moves from an absolute overlay into <uip-input>'s\n * prefix slot (same visual result, no overlay positioning to maintain).\n */\nexport class UipOrderManagementPage extends LitElement {\n  static shadowRootOptions = { ...LitElement.shadowRootOptions, delegatesFocus: true }\n  // :host display can't be a utility class (the host has no template of its own).\n  static styles = [tailwind, css`:host { display: block; }`]\n\n  static properties = {\n    search: { state: true },\n    statusFilter: { state: true },\n    selected: { state: true },\n    selectedOrder: { state: true },\n    drawerOpen: { state: true },\n  }\n\n  private search = ''\n  private statusFilter: 'all' | OrderStatus = 'all'\n  private selected: Set<string> = new Set()\n  private selectedOrder: Order | null = null\n  private drawerOpen = false\n\n  constructor() {\n    super()\n    new ThemeController(this)\n  }\n\n  connectedCallback() {\n    super.connectedCallback()\n    this.setAttribute('data-uipkge', '')\n    this.setAttribute('data-slot', 'order-management-page')\n  }\n\n  private get filteredOrders(): Order[] {\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  private get statusCounts(): Record<string, number> {\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  private toggleAll(checked: boolean) {\n    this.selected = checked ? new Set(this.filteredOrders.map((ord) => ord.id)) : new Set()\n  }\n\n  private toggleRow(id: string, checked: boolean) {\n    const next = new Set(this.selected)\n    if (checked) next.add(id)\n    else next.delete(id)\n    this.selected = next\n  }\n\n  private clearSelection() {\n    this.selected = new Set()\n  }\n\n  private openOrderDetails(order: Order) {\n    this.selectedOrder = order\n    this.drawerOpen = true\n  }\n\n  render() {\n    const filteredOrders = this.filteredOrders\n    const counts = this.statusCounts\n    const statusOptions = [\n      { value: 'all' as const, label: 'All', count: counts.all },\n      { value: 'paid' as const, label: 'Paid', count: counts.paid },\n      { value: 'processing' as const, label: 'Processing', count: counts.processing },\n      { value: 'shipped' as const, label: 'Shipped', count: counts.shipped },\n      { value: 'refunded' as const, label: 'Refunded', count: counts.refunded },\n    ]\n    const allSelected = filteredOrders.length > 0 && filteredOrders.every((ord) => this.selected.has(ord.id))\n    const someSelected = filteredOrders.some((ord) => this.selected.has(ord.id))\n    const order = this.selectedOrder\n\n    return html`\n      <div data-slot=\"order-management-page\" class=\"w-full space-y-6\">\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            <uip-button aria-label=\"Download attachment\" variant=\"outline\" size=\"sm\" class=\"text-xs\">\n              ${icon(Download, 'download', 'mr-1.5 size-3.5')} Export CSV\n            </uip-button>\n            <uip-button size=\"sm\" class=\"text-xs\"> ${icon(Plus, 'plus', 'mr-1.5 size-3.5')} New Order </uip-button>\n          </div>\n        </div>\n\n        <div class=\"grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4\">\n          <uip-card class=\"shadow-xs\">\n            <uip-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                  ${icon(ShoppingCart, 'shopping-cart', 'size-4')}\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                  ${icon(TrendingUp, 'trending-up', 'size-3.5')} +8.2%\n                </span>\n              </div>\n              <p class=\"text-muted-foreground mt-1 text-xs\">vs. previous 30 days</p>\n            </uip-card-content>\n          </uip-card>\n\n          <uip-card class=\"shadow-xs\">\n            <uip-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                  ${icon(Clock, 'clock', 'size-4')}\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 class=\"bg-warning/10 text-warning inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium\">\n                  12 urgent\n                </span>\n              </div>\n              <p class=\"text-muted-foreground mt-1 text-xs\">Requires warehouse dispatch</p>\n            </uip-card-content>\n          </uip-card>\n\n          <uip-card class=\"shadow-xs\">\n            <uip-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                  ${icon(PackageCheck, 'package-check', 'size-4')}\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            </uip-card-content>\n          </uip-card>\n\n          <uip-card class=\"shadow-xs\">\n            <uip-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                  ${icon(DollarSign, 'dollar-sign', 'size-4')}\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                  ${icon(ArrowUpRight, 'arrow-up-right', 'size-3.5')} +14.5%\n                </span>\n              </div>\n              <p class=\"text-muted-foreground mt-1 text-xs\">vs. previous period</p>\n            </uip-card-content>\n          </uip-card>\n        </div>\n\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            <uip-input\n              .value=${this.search}\n              placeholder=\"Search order ID, customer...\"\n              class=\"h-9 min-w-[240px] flex-1 text-xs sm:max-w-xs\"\n              @input=${(e: Event) => {\n                this.search = (e.target as UipInput).value ?? ''\n              }}\n            >\n              <span slot=\"prefix\">${icon(Search, 'search', 'size-4')}</span>\n            </uip-input>\n\n            <div class=\"bg-muted/60 flex items-center gap-1 rounded-lg border p-1\">\n              ${statusOptions.map(\n                (status) => html`<button\n                  type=\"button\"\n                  class=${cn(\n                    'rounded-md px-2.5 py-1 text-xs font-medium transition-colors',\n                    this.statusFilter === status.value\n                      ? 'bg-background text-foreground shadow-xs'\n                      : 'text-muted-foreground hover:text-foreground',\n                  )}\n                  @click=${() => {\n                    this.statusFilter = status.value\n                  }}\n                >\n                  ${status.label}\n                  ${status.count !== undefined\n                    ? html`<span\n                        class=${cn(\n                          'ml-1.5 rounded-full px-1.5 py-0.5 text-xs font-normal tabular-nums',\n                          this.statusFilter === status.value ? 'bg-muted text-foreground' : 'text-muted-foreground',\n                        )}\n                      >\n                        ${status.count}\n                      </span>`\n                    : nothing}\n                </button>`,\n              )}\n            </div>\n          </div>\n\n          <div class=\"flex items-center gap-2\">\n            <uip-button variant=\"outline\" size=\"sm\" class=\"text-xs font-normal\">\n              ${icon(Calendar, 'calendar', 'text-muted-foreground mr-1.5 size-3.5')} Last 30 days\n              ${icon(ChevronDown, 'chevron-down', 'text-muted-foreground ml-1.5 size-3.5')}\n            </uip-button>\n          </div>\n        </div>\n\n        ${this.selected.size > 0\n          ? html`<div class=\"bg-muted/50 flex flex-wrap items-center justify-between gap-2 rounded-lg border px-4 py-2.5 shadow-xs\">\n              <div class=\"flex items-center gap-2\">\n                <span class=\"bg-primary text-primary-foreground flex size-5 items-center justify-center rounded-full text-xs font-medium\">\n                  ${this.selected.size}\n                </span>\n                <span class=\"text-foreground text-sm font-medium\">\n                  ${this.selected.size} ${this.selected.size === 1 ? 'order' : 'orders'} selected\n                </span>\n              </div>\n              <div class=\"flex items-center gap-2\">\n                <uip-button\n                  aria-label=\"Download attachment\"\n                  variant=\"outline\"\n                  size=\"sm\"\n                  class=\"text-xs\"\n                  @click=${() => this.clearSelection()}\n                >\n                  ${icon(Download, 'download', 'mr-1.5 size-3.5')} Export selected\n                </uip-button>\n                <uip-button variant=\"outline\" size=\"sm\" class=\"text-xs\" @click=${() => this.clearSelection()}>\n                  ${icon(Truck, 'truck', 'mr-1.5 size-3.5')} Mark as shipped\n                </uip-button>\n                <uip-button\n                  variant=\"ghost\"\n                  size=\"sm\"\n                  class=\"text-destructive hover:text-destructive text-xs\"\n                  @click=${() => this.clearSelection()}\n                >\n                  Cancel\n                </uip-button>\n              </div>\n            </div>`\n          : nothing}\n\n        <div data-uipkge=\"\" data-slot=\"table-container\" class=\"bg-card relative w-full overflow-auto rounded-lg border shadow-xs\">\n          <table data-uipkge=\"\" data-slot=\"table\" class=\"w-full caption-bottom text-sm\">\n            <thead data-uipkge=\"\" data-slot=\"table-header\" class=\"bg-muted/50 [&_tr]:border-b\">\n              <tr data-uipkge=\"\" data-slot=\"table-row\" class=\"border-b transition-colors duration-150 hover:bg-transparent\">\n                <th\n                  data-uipkge=\"\"\n                  data-slot=\"table-head\"\n                  class=\"text-foreground h-10 px-3 text-left align-middle text-sm font-medium whitespace-nowrap [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px] w-10\"\n                >\n                  <uip-checkbox\n                    .checked=${allSelected}\n                    ?indeterminate=${!allSelected && someSelected}\n                    aria-label=\"Select all orders\"\n                    @checked-change=${(e: CustomEvent<{ checked: boolean }>) => this.toggleAll(e.detail.checked)}\n                  ></uip-checkbox>\n                </th>\n                <th\n                  data-uipkge=\"\"\n                  data-slot=\"table-head\"\n                  class=\"text-foreground h-10 px-3 text-left align-middle text-sm font-medium whitespace-nowrap [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px] min-w-[110px]\"\n                >\n                  Order ID\n                </th>\n                <th\n                  data-uipkge=\"\"\n                  data-slot=\"table-head\"\n                  class=\"text-foreground h-10 px-3 text-left align-middle text-sm font-medium whitespace-nowrap [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px] min-w-[100px]\"\n                >\n                  Date\n                </th>\n                <th\n                  data-uipkge=\"\"\n                  data-slot=\"table-head\"\n                  class=\"text-foreground h-10 px-3 text-left align-middle text-sm font-medium whitespace-nowrap [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px] min-w-[200px]\"\n                >\n                  Customer\n                </th>\n                <th\n                  data-uipkge=\"\"\n                  data-slot=\"table-head\"\n                  class=\"text-foreground h-10 px-3 text-left align-middle text-sm font-medium whitespace-nowrap [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px] min-w-[220px]\"\n                >\n                  Items\n                </th>\n                <th\n                  data-uipkge=\"\"\n                  data-slot=\"table-head\"\n                  class=\"text-foreground h-10 px-3 text-left align-middle text-sm font-medium whitespace-nowrap [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px] min-w-[90px] text-right\"\n                >\n                  Total\n                </th>\n                <th\n                  data-uipkge=\"\"\n                  data-slot=\"table-head\"\n                  class=\"text-foreground h-10 px-3 text-left align-middle text-sm font-medium whitespace-nowrap [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px] min-w-[120px]\"\n                >\n                  Fulfillment\n                </th>\n                <th\n                  data-uipkge=\"\"\n                  data-slot=\"table-head\"\n                  class=\"text-foreground h-10 px-3 text-left align-middle text-sm font-medium whitespace-nowrap [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px] w-10 text-right\"\n                >\n                  <span class=\"sr-only\">Actions</span>\n                </th>\n              </tr>\n            </thead>\n            <tbody data-uipkge=\"\" data-slot=\"table-body\" class=\"[&_tr:last-child]:border-0\">\n              ${filteredOrders.map(\n                (ord) => html`<tr\n                  data-uipkge=\"\"\n                  data-slot=\"table-row\"\n                  class=\"data-[state=selected]:bg-muted border-b transition-colors duration-150 group hover:bg-muted/40 cursor-pointer\"\n                  @click=${() => this.openOrderDetails(ord)}\n                >\n                  <td\n                    data-uipkge=\"\"\n                    data-slot=\"table-cell\"\n                    class=\"px-3 py-2 align-middle text-sm whitespace-nowrap [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px] w-10\"\n                    @click=${(e: Event) => e.stopPropagation()}\n                  >\n                    <uip-checkbox\n                      .checked=${this.selected.has(ord.id)}\n                      aria-label=${`Select order ${ord.orderNumber}`}\n                      @checked-change=${(e: CustomEvent<{ checked: boolean }>) => this.toggleRow(ord.id, e.detail.checked)}\n                    ></uip-checkbox>\n                  </td>\n                  <td\n                    data-uipkge=\"\"\n                    data-slot=\"table-cell\"\n                    class=\"px-3 py-2 align-middle text-sm whitespace-nowrap [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]\"\n                  >\n                    <span class=\"text-foreground font-mono text-xs font-semibold hover:underline\">${ord.orderNumber}</span>\n                  </td>\n                  <td\n                    data-uipkge=\"\"\n                    data-slot=\"table-cell\"\n                    class=\"px-3 py-2 align-middle text-sm whitespace-nowrap [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px] text-muted-foreground text-xs tabular-nums\"\n                  >\n                    ${ord.date}\n                  </td>\n                  <td\n                    data-uipkge=\"\"\n                    data-slot=\"table-cell\"\n                    class=\"px-3 py-2 align-middle text-sm whitespace-nowrap [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]\"\n                  >\n                    <div class=\"flex items-center gap-2.5\">\n                      <uip-avatar class=\"size-7\">\n                        <uip-avatar-fallback class=\"text-xs font-medium\">${initials(ord.customer.name)}</uip-avatar-fallback>\n                      </uip-avatar>\n                      <div class=\"min-w-0\">\n                        <p class=\"text-foreground truncate text-sm font-medium\">${ord.customer.name}</p>\n                        <p class=\"text-muted-foreground truncate text-xs\">${ord.customer.email}</p>\n                      </div>\n                    </div>\n                  </td>\n                  <td\n                    data-uipkge=\"\"\n                    data-slot=\"table-cell\"\n                    class=\"px-3 py-2 align-middle text-sm whitespace-nowrap [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]\"\n                  >\n                    <div class=\"text-xs\">\n                      <span class=\"text-foreground font-medium\">\n                        ${ord.items.reduce((acc, item) => acc + item.quantity, 0)}\n                        ${ord.items.reduce((acc, item) => acc + item.quantity, 0) === 1 ? 'item' : 'items'}\n                      </span>\n                      <span class=\"text-muted-foreground ml-1.5 inline-block max-w-[180px] truncate align-bottom\">\n                        • ${ord.items[0]?.name}${ord.items.length > 1 ? ` +${ord.items.length - 1} more` : ''}\n                      </span>\n                    </div>\n                  </td>\n                  <td\n                    data-uipkge=\"\"\n                    data-slot=\"table-cell\"\n                    class=\"px-3 py-2 align-middle text-sm whitespace-nowrap [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px] text-foreground text-right font-mono text-xs font-semibold tabular-nums\"\n                  >\n                    $${formatCurrency(ord.total)}\n                  </td>\n                  <td\n                    data-uipkge=\"\"\n                    data-slot=\"table-cell\"\n                    class=\"px-3 py-2 align-middle text-sm whitespace-nowrap [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]\"\n                  >\n                    <uip-badge\n                      variant=\"outline\"\n                      class=${cn('gap-1.5 px-2 py-0.5 text-xs font-medium capitalize', statusBadgeConfig[ord.status].class)}\n                    >\n                      <span class=${cn('size-1.5 rounded-full', statusBadgeConfig[ord.status].dot)} aria-hidden=\"true\"></span>\n                      ${statusBadgeConfig[ord.status].label}\n                    </uip-badge>\n                  </td>\n                  <td\n                    data-uipkge=\"\"\n                    data-slot=\"table-cell\"\n                    class=\"px-3 py-2 align-middle text-sm whitespace-nowrap [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px] text-right\"\n                    @click=${(e: Event) => e.stopPropagation()}\n                  >\n                    <uip-dropdown-menu class=\"[&::part(content)]:w-48 [&::part(refund)]:text-destructive\">\n                      <uip-button slot=\"trigger\" variant=\"ghost\" size=\"icon-sm\" class=\"text-muted-foreground hover:text-foreground\">\n                        ${icon(MoreHorizontal, 'ellipsis', 'size-4')}\n                        <span class=\"sr-only\">Actions for ${ord.orderNumber}</span>\n                      </uip-button>\n                      <uip-dropdown-menu-content align=\"end\">\n                        <uip-dropdown-menu-label>Order actions</uip-dropdown-menu-label>\n                        <uip-dropdown-menu-item @select=${() => this.openOrderDetails(ord)}>\n                          ${icon(Eye, 'eye', 'mr-2 size-4')} View details\n                        </uip-dropdown-menu-item>\n                        <uip-dropdown-menu-item>\n                          ${icon(FileText, 'file-text', 'mr-2 size-4')} Download invoice\n                        </uip-dropdown-menu-item>\n                        ${ord.status === 'processing'\n                          ? html`<uip-dropdown-menu-item>\n                              ${icon(Truck, 'truck', 'mr-2 size-4')} Mark as shipped\n                            </uip-dropdown-menu-item>`\n                          : nothing}\n                        <uip-dropdown-menu-separator></uip-dropdown-menu-separator>\n                        ${ord.status !== 'refunded'\n                          ? html`<uip-dropdown-menu-item part=\"refund\">\n                              ${icon(RotateCcw, 'rotate-ccw', 'mr-2 size-4')} Issue refund\n                            </uip-dropdown-menu-item>`\n                          : nothing}\n                      </uip-dropdown-menu-content>\n                    </uip-dropdown-menu>\n                  </td>\n                </tr>`,\n              )}\n              ${filteredOrders.length === 0\n                ? html`<tr data-uipkge=\"\" data-slot=\"table-row\" class=\"border-b transition-colors duration-150\">\n                    <td\n                      data-uipkge=\"\"\n                      data-slot=\"table-cell\"\n                      colSpan=\"8\"\n                      class=\"px-3 py-2 align-middle text-sm whitespace-nowrap text-muted-foreground h-32 text-center text-sm\"\n                    >\n                      No orders match your filter criteria.\n                    </td>\n                  </tr>`\n                : nothing}\n            </tbody>\n          </table>\n        </div>\n\n        <div class=\"flex flex-wrap items-center justify-between gap-4\">\n          <p class=\"text-muted-foreground text-xs tabular-nums\">Showing 1-${filteredOrders.length} of 1,429 orders</p>\n          <div class=\"flex items-center gap-2\">\n            <uip-button variant=\"outline\" size=\"sm\" class=\"text-xs\" disabled>Previous</uip-button>\n            <uip-button variant=\"outline\" size=\"sm\" class=\"text-xs\">Next</uip-button>\n          </div>\n        </div>\n\n        <uip-sheet\n          side=\"right\"\n          ?open=${this.drawerOpen}\n          heading=${order?.orderNumber ?? ''}\n          description=${order ? `Placed on ${order.date}` : ''}\n          @open-change=${(e: CustomEvent<{ open: boolean }>) => {\n            this.drawerOpen = e.detail.open\n          }}\n        >\n          ${order\n            ? html`<uip-sheet-body>\n                <div class=\"flex h-full flex-col\">\n                  <div class=\"flex items-center justify-between pr-6\">\n                    <span class=\"text-foreground font-mono text-base font-bold\">${order.orderNumber}</span>\n                    <uip-badge\n                      variant=\"outline\"\n                      class=${cn('gap-1.5 px-2.5 py-0.5 text-xs font-medium capitalize', statusBadgeConfig[order.status].class)}\n                    >\n                      <span class=${cn('size-1.5 rounded-full', statusBadgeConfig[order.status].dot)} aria-hidden=\"true\"></span>\n                      ${statusBadgeConfig[order.status].label}\n                    </uip-badge>\n                  </div>\n                  <div class=\"flex-1 space-y-6 overflow-y-auto py-5 text-sm\">\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\">Customer & Shipping</h4>\n                        <span class=\"text-muted-foreground font-mono text-xs\">${order.paymentMethod}</span>\n                      </div>\n                      <div class=\"flex items-center gap-3\">\n                        <uip-avatar class=\"size-9\">\n                          <uip-avatar-fallback class=\"text-xs font-semibold\">${initials(order.customer.name)}</uip-avatar-fallback>\n                        </uip-avatar>\n                        <div class=\"min-w-0\">\n                          <p class=\"text-foreground font-medium\">${order.customer.name}</p>\n                          <p class=\"text-muted-foreground text-xs\">${order.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>${order.customer.address}</p>\n                        <p>${order.customer.city}, ${order.customer.state} ${order.customer.zip}</p>\n                      </div>\n                    </div>\n\n                    ${order.carrier && order.trackingNumber\n                      ? html`<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\">Fulfillment</span>\n                            <uip-badge variant=\"secondary\" class=\"text-xs font-normal\">In Transit</uip-badge>\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\">${order.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\">${order.trackingNumber}</span>\n                          </div>\n                        </div>`\n                      : nothing}\n\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                        ${order.items.map(\n                          (item) => html`<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} × $${formatCurrency(item.price)}\n                              </p>\n                            </div>\n                            <div class=\"text-foreground font-mono text-xs font-semibold tabular-nums\">\n                              $${formatCurrency(item.price * item.quantity)}\n                            </div>\n                          </div>`,\n                        )}\n                      </div>\n                    </div>\n\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\">$${formatCurrency(order.subtotal)}</span>\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                          >${order.shipping === 0 ? 'Free' : `$${formatCurrency(order.shipping)}`}</span\n                        >\n                      </div>\n                      <div class=\"text-muted-foreground flex justify-between\">\n                        <span>Tax</span>\n                        <span class=\"text-foreground font-mono tabular-nums\">$${formatCurrency(order.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\">$${formatCurrency(order.total)}</span>\n                      </div>\n                    </div>\n                  </div>\n                </div>\n              </uip-sheet-body>`\n            : nothing}\n          <uip-button slot=\"footer\" aria-label=\"Download attachment\" variant=\"outline\" size=\"sm\" class=\"text-xs\">\n            ${icon(Download, 'download', 'mr-1.5 size-3.5')} Invoice PDF\n          </uip-button>\n          <uip-button slot=\"footer\" variant=\"secondary\" size=\"sm\" class=\"text-xs\" data-sheet-close>Close</uip-button>\n        </uip-sheet>\n      </div>\n    `\n  }\n}\n\ncustomElements.get('uip-order-management-page') ||\n  customElements.define('uip-order-management-page', UipOrderManagementPage)\n\ndeclare global {\n  interface HTMLElementTagNameMap {\n    'uip-order-management-page': UipOrderManagementPage\n  }\n}\n",
      "type": "registry:file",
      "target": "src/uip/blocks/order-management-page/order-management-page.ts"
    }
  ],
  "dependencies": [
    "lit",
    "lucide"
  ],
  "registryDependencies": [
    "https://uipkge.dev/r/lit/avatar.json",
    "https://uipkge.dev/r/lit/badge.json",
    "https://uipkge.dev/r/lit/button.json",
    "https://uipkge.dev/r/lit/card.json",
    "https://uipkge.dev/r/lit/checkbox.json",
    "https://uipkge.dev/r/lit/dropdown-menu.json",
    "https://uipkge.dev/r/lit/input.json",
    "https://uipkge.dev/r/lit/lit-core.json",
    "https://uipkge.dev/r/lit/sheet.json"
  ]
}
