{
  "$schema": "https://uipkge.dev/schema/registry-item.json",
  "name": "technical-specs-sheet",
  "title": "Technical Specs Sheet",
  "type": "registry:block",
  "description": "Comprehensive engineering technical specifications sheet with Metric/Imperial SI toggles, parameter category filters, search, and downloadable PDF trigger.",
  "categories": [
    "ecommerce",
    "data-display"
  ],
  "files": [
    {
      "path": "packages/elements-lit/src/blocks/technical-specs-sheet/technical-specs-sheet.ts",
      "content": "import { LitElement, css, html, nothing } from 'lit'\nimport { FileDown, ShieldCheck, CheckCircle2, Search, Info } from 'lucide'\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/badge/badge'\nimport '../../components/button/button'\nimport '../../components/card/card'\nimport '../../components/input/input'\nimport type { UipInput } from '../../components/input/input'\n\nexport interface SpecItem {\n  id: string\n  category: 'acoustic' | 'electrical' | 'physical' | 'connectivity' | 'compliance'\n  parameter: string\n  metricValue: string\n  imperialValue: string\n  tolerance?: string\n  testCondition?: string\n  highlight?: boolean\n}\n\nconst defaultSpecs: SpecItem[] = [\n  {\n    id: 's1',\n    category: 'acoustic',\n    parameter: 'Transducer Type',\n    metricValue: '50mm Planar-Magnetic with Neodymium N52 Array',\n    imperialValue: '1.97 in Planar-Magnetic with Neodymium N52 Array',\n    highlight: true,\n  },\n  {\n    id: 's2',\n    category: 'acoustic',\n    parameter: 'Frequency Response',\n    metricValue: '5 Hz – 52,000 Hz',\n    imperialValue: '5 Hz – 52,000 Hz',\n    tolerance: '± 0.5 dB (20 Hz - 20 kHz)',\n    highlight: true,\n  },\n  {\n    id: 's3',\n    category: 'acoustic',\n    parameter: 'Total Harmonic Distortion (THD)',\n    metricValue: '< 0.04% @ 1 kHz, 100 dB SPL',\n    imperialValue: '< 0.04% @ 1 kHz, 100 dB SPL',\n    testCondition: 'IEC 60268-7 Standard',\n  },\n  {\n    id: 's4',\n    category: 'acoustic',\n    parameter: 'Sound Pressure Level (SPL)',\n    metricValue: '106 dB / 1 mW @ 1 kHz',\n    imperialValue: '106 dB / 1 mW @ 1 kHz',\n    testCondition: 'Free-field calibrated',\n  },\n  {\n    id: 's5',\n    category: 'acoustic',\n    parameter: 'Acoustic Enclosure',\n    metricValue: 'Open-Back CNC Milled Aircraft-Grade Aluminum Grille',\n    imperialValue: 'Open-Back CNC Milled Aircraft-Grade Aluminum Grille',\n  },\n  {\n    id: 's6',\n    category: 'electrical',\n    parameter: 'Nominal Impedance',\n    metricValue: '32 Ω pure resistive load',\n    imperialValue: '32 Ω pure resistive load',\n    tolerance: '± 5% @ 1 kHz',\n    highlight: true,\n  },\n  {\n    id: 's7',\n    category: 'electrical',\n    parameter: 'Maximum Input Power Handling',\n    metricValue: '3,000 mW (3.0 W Continuous)',\n    imperialValue: '3,000 mW (3.0 W Continuous)',\n    testCondition: 'Thermal peak 5,000 mW (100ms)',\n  },\n  {\n    id: 's8',\n    category: 'electrical',\n    parameter: 'Recommended Amplifier Output',\n    metricValue: '250 mW – 2,000 mW @ 32 Ω',\n    imperialValue: '250 mW – 2,000 mW @ 32 Ω',\n  },\n  {\n    id: 's9',\n    category: 'physical',\n    parameter: 'Weight (excluding cable)',\n    metricValue: '385 grams',\n    imperialValue: '13.58 oz (0.85 lbs)',\n    tolerance: '± 5g',\n    highlight: true,\n  },\n  {\n    id: 's10',\n    category: 'physical',\n    parameter: 'Ear Cushion Dimensions (Inner ID)',\n    metricValue: '68 mm (H) × 52 mm (W) × 26 mm (D)',\n    imperialValue: '2.68 in (H) × 2.05 in (W) × 1.02 in (D)',\n  },\n  {\n    id: 's11',\n    category: 'physical',\n    parameter: 'Headband Clamping Force',\n    metricValue: '4.2 Newtons',\n    imperialValue: '0.94 lbf (Pound-force)',\n    tolerance: '± 0.3 N',\n  },\n  {\n    id: 's12',\n    category: 'physical',\n    parameter: 'Earpad Material Composition',\n    metricValue: 'Perforated Lambskin + Cooling Gel Memory Foam Core',\n    imperialValue: 'Perforated Lambskin + Cooling Gel Memory Foam Core',\n  },\n  {\n    id: 's13',\n    category: 'connectivity',\n    parameter: 'Headphone Terminals',\n    metricValue: 'Dual 3.5mm Gold-Plated TRRS Balanced Sockets',\n    imperialValue: 'Dual 1/8 in Gold-Plated TRRS Balanced Sockets',\n  },\n  {\n    id: 's14',\n    category: 'connectivity',\n    parameter: 'Included Studio Cable',\n    metricValue: '2.5 meter 8-Core Monocrystalline Silver-Plated Copper (OCC)',\n    imperialValue: '8.20 feet 8-Core Monocrystalline Silver-Plated Copper (OCC)',\n    highlight: true,\n  },\n  {\n    id: 's15',\n    category: 'connectivity',\n    parameter: 'Source Termination',\n    metricValue: '4.4mm Pentaconn Balanced + 6.35mm Gold-Plated Adapter',\n    imperialValue: '4.4mm Pentaconn Balanced + 1/4 in Gold-Plated Adapter',\n  },\n  {\n    id: 's16',\n    category: 'compliance',\n    parameter: 'Certifications & Directives',\n    metricValue: 'Hi-Res Audio Certified, CE Mark, FCC Class B, RoHS 3, WEEE',\n    imperialValue: 'Hi-Res Audio Certified, CE Mark, FCC Class B, RoHS 3, WEEE',\n    highlight: true,\n  },\n  {\n    id: 's17',\n    category: 'compliance',\n    parameter: 'Operating Temperature & Humidity',\n    metricValue: '-10°C to +45°C (10% to 90% RH non-condensing)',\n    imperialValue: '14°F to 113°F (10% to 90% RH non-condensing)',\n  },\n]\n\nconst categories = [\n  { id: 'all', label: 'All Specifications' },\n  { id: 'acoustic', label: 'Acoustic Architecture' },\n  { id: 'electrical', label: 'Electrical & Power' },\n  { id: 'physical', label: 'Dimensions & Weight' },\n  { id: 'connectivity', label: 'Cables & Interconnects' },\n  { id: 'compliance', label: 'Standards & Compliance' },\n]\n\n/**\n * <uip-technical-specs-sheet> — the registry TechnicalSpecsSheet block as a web component.\n *\n * Class strings and spec data are React's verbatim. React state becomes\n * { state: true } fields; `specs` is a property (attribute: false — set it from\n * JS). React's `downloadPdf` alert becomes a `download-pdf` CustomEvent\n * (bubbles, composed). The spec grid uses a native <table> with the registry\n * Table part classes copied verbatim — <uip-table>'s data-driven API can't\n * express per-row highlight classes or the empty-state spanning row. The\n * search icon moves from an absolute overlay into <uip-input>'s prefix slot.\n */\nexport class UipTechnicalSpecsSheet 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    modelNumber: { attribute: 'model-number' },\n    revision: {},\n    specs: { attribute: false },\n    isMetric: { state: true },\n    activeCategory: { state: true },\n    searchQuery: { state: true },\n  }\n\n  modelNumber = 'APX-950-PRO'\n  revision = 'Rev 2.4 (2026)'\n  specs: SpecItem[] = defaultSpecs\n\n  private isMetric = true\n  private activeCategory = 'all'\n  private searchQuery = ''\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', 'technical-specs-sheet')\n  }\n\n  private get filteredSpecs(): SpecItem[] {\n    return (this.specs ?? []).filter((item) => {\n      const matchesCat = this.activeCategory === 'all' || item.category === this.activeCategory\n      const matchesSearch =\n        this.searchQuery.trim() === '' ||\n        item.parameter.toLowerCase().includes(this.searchQuery.toLowerCase()) ||\n        item.metricValue.toLowerCase().includes(this.searchQuery.toLowerCase()) ||\n        item.imperialValue.toLowerCase().includes(this.searchQuery.toLowerCase())\n      return matchesCat && matchesSearch\n    })\n  }\n\n  render() {\n    const filteredSpecs = this.filteredSpecs\n    // data-slot lives on this wrapper: <uip-card> stamps its own\n    // data-slot=\"card\" on connect, which would clobber the block slot.\n    return html`\n      <div data-slot=\"technical-specs-sheet\">\n        <uip-card class=\"border-border w-full shadow-xs\">\n          <uip-card-header class=\"border-border bg-muted/20 border-b pb-4\">\n            <div class=\"flex flex-col gap-4 lg:flex-row lg:items-center lg:justify-between\">\n              <div>\n                <div class=\"flex items-center gap-2\">\n                  <span class=\"text-muted-foreground font-mono text-xs font-semibold tracking-wider uppercase\">\n                    ${this.modelNumber} · ${this.revision}\n                  </span>\n                  <uip-badge variant=\"outline\" class=\"text-success font-mono text-xs\">Laboratory Certified</uip-badge>\n                </div>\n                <uip-card-title class=\"text-foreground text-lg font-semibold tracking-tight sm:text-xl\">\n                  Engineering & Technical Specifications Sheet\n                </uip-card-title>\n                <uip-card-description class=\"text-xs\">\n                  Comprehensive acoustic measurements, electrical parameters, material tolerances, and compliance standards.\n                </uip-card-description>\n              </div>\n\n              <div class=\"flex flex-wrap items-center gap-2.5\">\n                <div class=\"border-border bg-background flex items-center rounded-lg border p-0.5 text-xs shadow-2xs\">\n                  <button\n                    type=\"button\"\n                    class=${`rounded-md px-2.5 py-1 font-medium transition-colors ${\n                      this.isMetric\n                        ? 'bg-primary text-primary-foreground font-semibold shadow-2xs'\n                        : 'text-muted-foreground hover:text-foreground'\n                    }`}\n                    @click=${() => {\n                      this.isMetric = true\n                    }}\n                  >\n                    Metric (SI)\n                  </button>\n                  <button\n                    type=\"button\"\n                    class=${`rounded-md px-2.5 py-1 font-medium transition-colors ${\n                      !this.isMetric\n                        ? 'bg-primary text-primary-foreground font-semibold shadow-2xs'\n                        : 'text-muted-foreground hover:text-foreground'\n                    }`}\n                    @click=${() => {\n                      this.isMetric = false\n                    }}\n                  >\n                    Imperial (US)\n                  </button>\n                </div>\n                <uip-button\n                  variant=\"outline\"\n                  size=\"sm\"\n                  class=\"gap-1.5 text-xs shadow-2xs\"\n                  @click=${() => this.dispatchEvent(new CustomEvent('download-pdf', { bubbles: true, composed: true }))}\n                >\n                  ${icon(FileDown, 'file-down', 'size-3.5')}\n                  <span>Download Spec PDF</span>\n                </uip-button>\n              </div>\n            </div>\n\n            <div class=\"mt-4 flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between\">\n              <div class=\"flex flex-wrap items-center gap-1.5\">\n                ${categories.map(\n                  (cat) => html`<button\n                    type=\"button\"\n                    class=${`rounded-md px-2.5 py-1 text-xs font-medium transition-colors ${\n                      this.activeCategory === cat.id\n                        ? 'bg-foreground text-background shadow-2xs'\n                        : 'bg-muted/60 text-muted-foreground hover:bg-muted hover:text-foreground border border-transparent'\n                    }`}\n                    @click=${() => {\n                      this.activeCategory = cat.id\n                    }}\n                  >\n                    ${cat.label}\n                  </button>`,\n                )}\n              </div>\n              <uip-input\n                .value=${this.searchQuery}\n                placeholder=\"Search parameters...\"\n                class=\"h-8 w-full text-xs sm:w-64\"\n                @input=${(e: Event) => {\n                  this.searchQuery = (e.target as UipInput).value ?? ''\n                }}\n              >\n                <span slot=\"prefix\">${icon(Search, 'search', 'size-3.5')}</span>\n              </uip-input>\n            </div>\n          </uip-card-header>\n\n          <uip-card-content class=\"p-0\">\n            <div data-uipkge=\"\" data-slot=\"table-container\" class=\"relative w-full overflow-auto\">\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 w-[280px]\"\n                    >\n                      Parameter / Measurement\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\"\n                    >\n                      Specification (${this.isMetric ? 'Metric' : 'Imperial'})\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 w-[180px]\"\n                    >\n                      Tolerance / Range\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 w-[220px]\"\n                    >\n                      Test Standard / Method\n                    </th>\n                  </tr>\n                </thead>\n                <tbody data-uipkge=\"\" data-slot=\"table-body\" class=\"[&_tr:last-child]:border-0\">\n                  ${filteredSpecs.map(\n                    (spec) => html`<tr\n                      data-uipkge=\"\"\n                      data-slot=\"table-row\"\n                      class=${`border-b transition-colors duration-150 hover:bg-muted/50 ${spec.highlight ? 'bg-primary/5' : ''}`}\n                    >\n                      <td data-uipkge=\"\" data-slot=\"table-cell\" class=\"px-3 py-2 align-middle text-sm whitespace-nowrap\">\n                        <div class=\"flex items-center gap-2\">\n                          <span class=\"text-foreground text-xs font-medium\">${spec.parameter}</span>\n                          ${spec.highlight\n                            ? html`<uip-badge variant=\"secondary\" class=\"h-4.5 px-1.5 font-mono text-xs font-semibold uppercase\">\n                                Key Spec\n                              </uip-badge>`\n                            : nothing}\n                        </div>\n                      </td>\n                      <td data-uipkge=\"\" data-slot=\"table-cell\" class=\"px-3 py-2 align-middle text-sm whitespace-nowrap\">\n                        <span class=\"text-foreground font-mono text-xs font-semibold\"\n                          >${this.isMetric ? spec.metricValue : spec.imperialValue}</span\n                        >\n                      </td>\n                      <td data-uipkge=\"\" data-slot=\"table-cell\" class=\"px-3 py-2 align-middle text-sm whitespace-nowrap\">\n                        <span class=\"text-muted-foreground font-mono text-xs\">${spec.tolerance || '—'}</span>\n                      </td>\n                      <td data-uipkge=\"\" data-slot=\"table-cell\" class=\"px-3 py-2 align-middle text-sm whitespace-nowrap\">\n                        <span class=\"text-muted-foreground text-xs\">${spec.testCondition || 'Factory Standard Q/C'}</span>\n                      </td>\n                    </tr>`,\n                  )}\n                  ${filteredSpecs.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=\"4\"\n                          class=\"px-3 py-2 align-middle text-sm whitespace-nowrap text-muted-foreground h-28 text-center text-xs\"\n                        >\n                          No matching specifications found for &quot;${this.searchQuery}&quot;.\n                        </td>\n                      </tr>`\n                    : nothing}\n                </tbody>\n              </table>\n            </div>\n\n            <div class=\"border-border bg-muted/20 flex flex-wrap items-center justify-between gap-3 border-t p-4 text-xs\">\n              <div class=\"text-muted-foreground flex flex-wrap items-center gap-4\">\n                <div class=\"flex items-center gap-1.5\">\n                  ${icon(ShieldCheck, 'shield-check', 'text-primary size-4')}\n                  <span class=\"text-foreground font-medium\">Calibrated Precision</span>\n                </div>\n                <div class=\"flex items-center gap-1.5\">\n                  ${icon(CheckCircle2, 'circle-check', 'text-success size-4')}\n                  <span>3-Year Studio Warranty Included</span>\n                </div>\n                <div class=\"flex items-center gap-1.5\">\n                  ${icon(Info, 'info', 'text-info size-4')}\n                  <span>Serial matched drivers (± 0.3 dB stereo tracking)</span>\n                </div>\n              </div>\n              <span class=\"text-muted-foreground font-mono text-xs\">Document ID: SPEC-APX-${this.modelNumber}-2026</span>\n            </div>\n          </uip-card-content>\n        </uip-card>\n      </div>\n    `\n  }\n}\n\ncustomElements.get('uip-technical-specs-sheet') || customElements.define('uip-technical-specs-sheet', UipTechnicalSpecsSheet)\n\ndeclare global {\n  interface HTMLElementTagNameMap {\n    'uip-technical-specs-sheet': UipTechnicalSpecsSheet\n  }\n}\n",
      "type": "registry:file",
      "target": "src/uip/blocks/technical-specs-sheet/technical-specs-sheet.ts"
    }
  ],
  "dependencies": [
    "lit",
    "lucide"
  ],
  "registryDependencies": [
    "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/input.json",
    "https://uipkge.dev/r/lit/lit-core.json"
  ]
}
