{
  "$schema": "https://uipkge.dev/schema/registry-item.json",
  "name": "error-404",
  "title": "404 Not Found",
  "type": "registry:block",
  "description": "Full-page 404 with an isometric missing-page illustration, HTTP code, headline, and Back to home + Contact support. Prop-driven: pass title, description, image, action labels, hrefs, and layout (`page` | `contained`). Pass `image=\"\"` to hide the art.",
  "categories": [
    "layout",
    "feedback"
  ],
  "deprecated": true,
  "replacedBy": "error-page",
  "files": [
    {
      "path": "packages/elements-lit/src/blocks/error-404/error-404.ts",
      "content": "import { LitElement, css, html, nothing } from 'lit'\nimport { ArrowLeft, LifeBuoy } 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 import: registers <uip-button> for standalone use (consumers\n// who install only this block still get a working button).\nimport '../../components/button/button'\n\n/**\n * <uip-error-404> — the registry Error404 block as a web component.\n *\n * Class strings are React's Error404 verbatim. `heading` is React's `title`\n * (`title` is taken by HTMLElement). `onPrimary` / `onSecondary` become\n * `primary` / `secondary` CustomEvents (bubbles, composed). React's\n * `image === undefined` HTTP-panel branch is unreachable (its default param\n * fills `image` first), so it is not ported: omit `image` for the default\n * art, pass `image=\"\"` to hide it.\n */\nexport class UipError404 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    code: {},\n    heading: {},\n    description: {},\n    image: {},\n    imageAlt: { attribute: 'image-alt' },\n    primaryLabel: { attribute: 'primary-label' },\n    secondaryLabel: { attribute: 'secondary-label' },\n    primaryHref: { attribute: 'primary-href' },\n    secondaryHref: { attribute: 'secondary-href' },\n    showPrimary: { type: Boolean, attribute: 'show-primary' },\n    showSecondary: { type: Boolean, attribute: 'show-secondary' },\n    primaryDisabled: { type: Boolean, attribute: 'primary-disabled' },\n    secondaryDisabled: { type: Boolean, attribute: 'secondary-disabled' },\n    layout: { reflect: true },\n  }\n\n  code?: string\n  heading?: string\n  description?: string\n  image = '/illustrations/error-404.jpg'\n  imageAlt = ''\n  primaryLabel?: string\n  secondaryLabel?: string\n  primaryHref?: string\n  secondaryHref?: string\n  showPrimary = true\n  showSecondary = true\n  primaryDisabled = false\n  secondaryDisabled = false\n  layout: 'page' | 'contained' = 'page'\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', 'error-404')\n    this.setAttribute('data-layout', this.layout)\n  }\n\n  willUpdate() {\n    this.setAttribute('data-layout', this.layout)\n  }\n\n  private emit(name: 'primary' | 'secondary') {\n    this.dispatchEvent(new CustomEvent(name, { bubbles: true, composed: true }))\n  }\n\n  render() {\n    const codeText = this.code ?? '404'\n    const titleText = this.heading ?? 'Page not found'\n    const descriptionText =\n      this.description ?? \"The page you're looking for doesn't exist or may have been moved. Check the URL or head back home.\"\n    const primaryText = this.primaryLabel ?? 'Back to home'\n    const secondaryText = this.secondaryLabel ?? 'Contact support'\n    return html`\n      <section\n        data-slot=\"error-404\"\n        data-layout=${this.layout}\n        class=${cn(\n          'bg-background relative flex items-center overflow-hidden px-6 py-16',\n          this.layout === 'page' ? 'min-h-svh' : 'min-h-[28rem]',\n        )}\n      >\n        <div class=\"mx-auto grid w-full max-w-5xl items-center gap-10 lg:grid-cols-2 lg:gap-16\">\n          <div>\n            ${codeText\n              ? html`<p class=\"text-muted-foreground text-sm font-medium\">HTTP ${codeText}</p>\n                  <p class=\"mt-3 text-6xl font-semibold tracking-tighter sm:text-7xl\">${codeText}</p>`\n              : nothing}\n            <h1 class=\"mt-3 text-2xl font-semibold tracking-tight sm:text-3xl\">${titleText}</h1>\n            ${descriptionText\n              ? html`<p class=\"text-muted-foreground mt-4 max-w-md text-base\">${descriptionText}</p>`\n              : nothing}\n            ${this.showPrimary || this.showSecondary\n              ? html`<div class=\"mt-8 flex flex-wrap items-center gap-3\">\n                  ${this.showPrimary\n                    ? html`<uip-button\n                        size=\"lg\"\n                        ?disabled=${this.primaryDisabled}\n                        href=${this.primaryHref ?? nothing}\n                        @click=${() => this.emit('primary')}\n                      >\n                        ${icon(ArrowLeft, 'arrow-left')} ${primaryText}\n                      </uip-button>`\n                    : nothing}\n                  ${this.showSecondary\n                    ? html`<uip-button\n                        size=\"lg\"\n                        variant=\"outline\"\n                        ?disabled=${this.secondaryDisabled}\n                        href=${this.secondaryHref ?? nothing}\n                        @click=${() => this.emit('secondary')}\n                      >\n                        ${secondaryText} ${icon(LifeBuoy, 'life-buoy')}\n                      </uip-button>`\n                    : nothing}\n                </div>`\n              : nothing}\n          </div>\n          ${this.image\n            ? html`<div class=\"border-border bg-muted overflow-hidden rounded-xl border\">\n                <img src=${this.image} alt=${this.imageAlt} class=\"aspect-[4/3] w-full object-cover\" />\n              </div>`\n            : nothing}\n        </div>\n      </section>\n    `\n  }\n}\n\ncustomElements.get('uip-error-404') || customElements.define('uip-error-404', UipError404)\n\ndeclare global {\n  interface HTMLElementTagNameMap {\n    'uip-error-404': UipError404\n  }\n}\n",
      "type": "registry:file",
      "target": "src/uip/blocks/error-404/error-404.ts"
    }
  ],
  "dependencies": [
    "lit",
    "lucide"
  ],
  "registryDependencies": [
    "https://uipkge.dev/r/lit/button.json",
    "https://uipkge.dev/r/lit/lit-core.json"
  ]
}
