{
  "$schema": "https://uipkge.dev/schema/registry-item.json",
  "name": "error-pages",
  "title": "Error Pages",
  "type": "registry:block",
  "files": [
    {
      "path": "packages/registry-svelte/blocks/error-pages/ErrorPages.svelte",
      "content": "<script lang=\"ts\" module>\n  import type { Component } from 'svelte'\n\n  export type ErrorPagesVariant = '404' | '500' | '403' | 'maintenance'\n\n  export interface ErrorPagesProps {\n    /** `'all'` renders the full gallery; a single variant renders just that screen. */\n    variant?: ErrorPagesVariant | 'all'\n    size?: 'sm' | 'default'\n    class?: string\n    title?: string\n    description?: string\n    /** Status numeral. Pass `''` to hide. */\n    code?: string\n    /** Eyebrow pill (maintenance ETA by default). Pass `''` to hide. */\n    tag?: string\n    /** Replaces the HTTP response panel on a single variant. Pass `''` to hide art. */\n    image?: string\n    imageAlt?: string\n    primaryLabel?: string\n    secondaryLabel?: string\n    primaryHref?: string\n    secondaryHref?: string\n    showPrimary?: boolean\n    showSecondary?: boolean\n    primaryDisabled?: boolean\n    secondaryDisabled?: boolean\n    onHome?: () => void\n    onSearch?: () => void\n    onRetry?: () => void\n    onStatus?: () => void\n    onSwitchAccount?: () => void\n    onRequestAccess?: () => void\n    onSubscribe?: () => void\n  }\n</script>\n\n<script lang=\"ts\">\n  import { Clock, RotateCcw } from '@lucide/svelte'\n  import { cn } from '$lib/utils'\n  import { Button, buttonVariants, type ButtonVariants } from '$lib/components/ui/button'\n\n  let {\n    variant = 'all',\n    size = 'default',\n    class: className,\n    title,\n    description,\n    code,\n    tag,\n    image,\n    imageAlt = '',\n    primaryLabel,\n    secondaryLabel,\n    primaryHref,\n    secondaryHref,\n    showPrimary = true,\n    showSecondary = true,\n    primaryDisabled = false,\n    secondaryDisabled = false,\n    onHome,\n    onSearch,\n    onRetry,\n    onStatus,\n    onSwitchAccount,\n    onRequestAccess,\n    onSubscribe,\n  }: ErrorPagesProps = $props()\n\n  const show = (v: ErrorPagesVariant) => variant === 'all' || variant === v\n  const copy = (fallback: string, override?: string) => (override === undefined ? fallback : override)\n  const forVariant = (v: ErrorPagesVariant, fallback: string, override?: string) =>\n    variant === v ? copy(fallback, override) : fallback\n\n  const title404 = $derived(forVariant('404', 'Page not found', title))\n  const desc404 = $derived(\n    forVariant(\n      '404',\n      \"The page you're looking for doesn't exist or was moved. Check the URL or head back home.\",\n      description,\n    ),\n  )\n  const code404 = $derived(forVariant('404', '404', code))\n  const image404 = $derived(forVariant('404', '/illustrations/error-404.jpg', image))\n  const primary404 = $derived(forVariant('404', 'Go home', primaryLabel))\n  const secondary404 = $derived(forVariant('404', 'Search docs', secondaryLabel))\n\n  const title500 = $derived(forVariant('500', 'Internal server error', title))\n  const desc500 = $derived(\n    forVariant(\n      '500',\n      'Something went wrong on our end. The team has been notified — try again in a moment.',\n      description,\n    ),\n  )\n  const code500 = $derived(forVariant('500', '500', code))\n  const image500 = $derived(forVariant('500', '/illustrations/error-500.jpg', image))\n  const primary500 = $derived(forVariant('500', 'Retry', primaryLabel))\n  const secondary500 = $derived(forVariant('500', 'Status page', secondaryLabel))\n\n  const title403 = $derived(forVariant('403', 'Access denied', title))\n  const desc403 = $derived(\n    forVariant(\n      '403',\n      \"You don't have permission to view this page. Switch accounts or ask an admin to request access.\",\n      description,\n    ),\n  )\n  const code403 = $derived(forVariant('403', '403', code))\n  const image403 = $derived(forVariant('403', '/illustrations/error-403.jpg', image))\n  const primary403 = $derived(forVariant('403', 'Request access', primaryLabel))\n  const secondary403 = $derived(forVariant('403', 'Switch account', secondaryLabel))\n\n  const title503 = $derived(forVariant('maintenance', 'Scheduled maintenance', title))\n  const desc503 = $derived(\n    forVariant('maintenance', \"We're upgrading our systems. The service will be back online shortly.\", description),\n  )\n  const code503 = $derived(forVariant('maintenance', '503', code))\n  const image503 = $derived(forVariant('maintenance', '/illustrations/error-maintenance.jpg', image))\n  const tag503 = $derived(forVariant('maintenance', 'Back online around 14:00 UTC', tag))\n  const primary503 = $derived(forVariant('maintenance', 'Subscribe for updates', primaryLabel))\n  const secondary503 = $derived(variant === 'maintenance' ? (secondaryLabel ?? '') : (secondaryLabel ?? ''))\n\n  const frameClass = $derived(\n    cn('border-border bg-card overflow-hidden rounded-xl border text-left', size === 'sm' && 'rounded-lg'),\n  )\n  const imgClass = 'aspect-[16/10] w-full object-cover'\n  const panelClass = 'border-border bg-muted/40 border-b font-mono'\n  const bodyClass = $derived(size === 'sm' ? 'p-5' : 'p-6')\n  const codeClass = $derived(cn('font-semibold tracking-tighter', size === 'sm' ? 'text-2xl' : 'text-4xl'))\n  const titleClass = $derived(cn('mt-1.5 font-semibold tracking-tight', size === 'sm' ? 'text-base' : 'text-xl'))\n  const descClass = 'text-muted-foreground mt-2 max-w-sm text-sm'\n  const actionsClass = $derived(cn('flex flex-wrap items-center gap-2', size === 'sm' ? 'mt-4' : 'mt-5'))\n  const actionSize = $derived(size === 'sm' ? 'xs' : 'sm')\n</script>\n\n{#snippet actionButton(\n  href: string | undefined,\n  label: string,\n  variantName: ButtonVariants['variant'] = 'default',\n  disabled = false,\n  onclick?: () => void,\n  Icon?: Component,\n)}\n  {#if href}\n    <a {href} class={buttonVariants({ variant: variantName, size: actionSize })} {onclick} aria-disabled={disabled}>\n      {#if Icon}\n        <Icon />\n      {/if}\n      {label}\n    </a>\n  {:else}\n    <Button variant={variantName} size={actionSize} {disabled} {onclick}>\n      {#if Icon}\n        <Icon />\n      {/if}\n      {label}\n    </Button>\n  {/if}\n{/snippet}\n\n<div data-slot=\"error-pages\" data-size={size} class={cn(variant === 'all' && 'grid gap-4 sm:grid-cols-2', className)}>\n  {#if show('404')}\n    <article class={frameClass} data-slot=\"error-page\" data-variant=\"404\" role=\"status\">\n      {#if image404}\n        <img src={image404} alt={imageAlt} class={imgClass} />\n      {:else if image404 === undefined}\n        <div class={panelClass} aria-hidden=\"true\">\n          <div class=\"border-border text-muted-foreground truncate border-b px-3 py-2 text-xs\">GET /pricing/teams</div>\n          <div class=\"space-y-1 p-3 text-xs leading-relaxed\">\n            <p><span class=\"text-muted-foreground\">HTTP/1.1</span> {code404 || '404'} Not Found</p>\n            <p class=\"text-muted-foreground\">x-request-id: req_9k2e18</p>\n          </div>\n        </div>\n      {/if}\n      <div class={bodyClass}>\n        {#if code404}\n          <p class={codeClass}>{code404}</p>\n        {/if}\n        <h3 class={titleClass}>{title404}</h3>\n        <p class={descClass}>{desc404}</p>\n        {#if variant === '404' && tag}\n          <p class=\"text-muted-foreground mt-3 inline-flex items-center rounded-full border px-3 py-1 text-xs\">\n            {tag}\n          </p>\n        {/if}\n        {#if showPrimary || showSecondary}\n          <div class={actionsClass}>\n            {#if showPrimary}\n              {@render actionButton(primaryHref, primary404, 'default', primaryDisabled, onHome)}\n            {/if}\n            {#if showSecondary}\n              {@render actionButton(secondaryHref, secondary404, 'ghost', secondaryDisabled, onSearch)}\n            {/if}\n          </div>\n        {/if}\n      </div>\n    </article>\n  {/if}\n\n  {#if show('500')}\n    <article class={frameClass} data-slot=\"error-page\" data-variant=\"500\" role=\"alert\">\n      {#if image500}\n        <img src={image500} alt={imageAlt} class={imgClass} />\n      {:else if image500 === undefined}\n        <div class={panelClass} aria-hidden=\"true\">\n          <div class=\"border-border text-muted-foreground truncate border-b px-3 py-2 text-xs\">POST /api/v1/invoices</div>\n          <div class=\"space-y-1 p-3 text-xs leading-relaxed\">\n            <p>\n              <span class=\"text-muted-foreground\">HTTP/1.1</span>\n              <span class=\"text-destructive\">{code500 || '500'} Internal Server Error</span>\n            </p>\n            <p class=\"text-muted-foreground\">error: ECONNRESET at Worker.run:142</p>\n          </div>\n        </div>\n      {/if}\n      <div class={bodyClass}>\n        {#if code500}\n          <p class={codeClass}>{code500}</p>\n        {/if}\n        <h3 class={titleClass}>{title500}</h3>\n        <p class={descClass}>{desc500}</p>\n        {#if variant === '500' && tag}\n          <p class=\"text-muted-foreground mt-3 inline-flex items-center rounded-full border px-3 py-1 text-xs\">\n            {tag}\n          </p>\n        {/if}\n        {#if showPrimary || showSecondary}\n          <div class={actionsClass}>\n            {#if showPrimary}\n              {@render actionButton(primaryHref, primary500, 'default', primaryDisabled, onRetry, RotateCcw)}\n            {/if}\n            {#if showSecondary}\n              {@render actionButton(secondaryHref, secondary500, 'outline', secondaryDisabled, onStatus)}\n            {/if}\n          </div>\n        {/if}\n      </div>\n    </article>\n  {/if}\n\n  {#if show('403')}\n    <article class={frameClass} data-slot=\"error-page\" data-variant=\"403\" role=\"alert\">\n      {#if image403}\n        <img src={image403} alt={imageAlt} class={imgClass} />\n      {:else if image403 === undefined}\n        <div class={panelClass} aria-hidden=\"true\">\n          <div class=\"border-border text-muted-foreground truncate border-b px-3 py-2 text-xs\">GET /admin/billing</div>\n          <div class=\"space-y-1 p-3 text-xs leading-relaxed\">\n            <p>\n              <span class=\"text-muted-foreground\">HTTP/1.1</span>\n              <span class=\"text-warning\">{code403 || '403'} Forbidden</span>\n            </p>\n            <p class=\"text-muted-foreground\">scope billing:read — denied for guest</p>\n          </div>\n        </div>\n      {/if}\n      <div class={bodyClass}>\n        {#if code403}\n          <p class={codeClass}>{code403}</p>\n        {/if}\n        <h3 class={titleClass}>{title403}</h3>\n        <p class={descClass}>{desc403}</p>\n        {#if variant === '403' && tag}\n          <p class=\"text-muted-foreground mt-3 inline-flex items-center rounded-full border px-3 py-1 text-xs\">\n            {tag}\n          </p>\n        {/if}\n        {#if showPrimary || showSecondary}\n          <div class={actionsClass}>\n            {#if showSecondary}\n              {@render actionButton(secondaryHref, secondary403, 'outline', secondaryDisabled, onSwitchAccount)}\n            {/if}\n            {#if showPrimary}\n              {@render actionButton(primaryHref, primary403, 'default', primaryDisabled, onRequestAccess)}\n            {/if}\n          </div>\n        {/if}\n      </div>\n    </article>\n  {/if}\n\n  {#if show('maintenance')}\n    <article class={frameClass} data-slot=\"error-page\" data-variant=\"maintenance\" role=\"status\">\n      {#if image503}\n        <img src={image503} alt={imageAlt} class={imgClass} />\n      {:else if image503 === undefined}\n        <div class={panelClass} aria-hidden=\"true\">\n          <div class=\"border-border text-muted-foreground truncate border-b px-3 py-2 text-xs\">GET /health</div>\n          <div class=\"space-y-1 p-3 text-xs leading-relaxed\">\n            <p>\n              <span class=\"text-muted-foreground\">HTTP/1.1</span>\n              <span class=\"text-warning\">{code503 || '503'} Service Unavailable</span>\n            </p>\n            <p class=\"text-muted-foreground\">Retry-After: 3600</p>\n          </div>\n        </div>\n      {/if}\n      <div class={bodyClass}>\n        {#if code503}\n          <p class={codeClass}>{code503}</p>\n        {/if}\n        <h3 class={titleClass}>{title503}</h3>\n        <p class={descClass}>{desc503}</p>\n        {#if tag503}\n          <p class=\"text-muted-foreground mt-3 inline-flex items-center gap-1.5 rounded-full border px-3 py-1 text-xs\">\n            <Clock class=\"size-3.5\" aria-hidden=\"true\" />\n            {tag503}\n          </p>\n        {/if}\n        {#if showPrimary || (showSecondary && secondary503)}\n          <div class={actionsClass}>\n            {#if showPrimary}\n              {@render actionButton(primaryHref, primary503, 'ghost', primaryDisabled, onSubscribe)}\n            {/if}\n            {#if showSecondary && secondary503}\n              {@render actionButton(secondaryHref, secondary503, 'outline', secondaryDisabled, onStatus)}\n            {/if}\n          </div>\n        {/if}\n      </div>\n    </article>\n  {/if}\n</div>\n",
      "type": "registry:block",
      "target": "~/src/lib/components/blocks/error-pages/ErrorPages.svelte"
    },
    {
      "path": "packages/registry-svelte/blocks/error-pages/page.svelte",
      "content": "<script lang=\"ts\">\n  // Demo page wired by `npx shadcn-svelte@latest add https://uipkge.dev/r/svelte/error-pages.json`.\n  // Visit /error-pages-demo after install.\n  import ErrorPages from '$lib/components/blocks/error-pages/ErrorPages.svelte'\n</script>\n\n<div class=\"bg-background min-h-svh\">\n  <header class=\"border-border border-b px-8 py-4\">\n    <h1 class=\"text-muted-foreground font-mono text-sm tracking-widest break-all uppercase\">error-pages demo</h1>\n  </header>\n  <main class=\"p-8\">\n    <ErrorPages />\n  </main>\n</div>\n",
      "type": "registry:block",
      "target": "~/src/routes/error-pages-demo/+page.svelte"
    }
  ],
  "dependencies": [
    "@lucide/svelte"
  ],
  "devDependencies": [],
  "registryDependencies": [
    "https://uipkge.dev/r/svelte/button.json"
  ],
  "description": "Pack of four status screens — 404, 500, 403, and 503 — each with a matching isometric illustration, code, copy, and actions. `variant` picks a single screen, `size` compacts it. Override title, description, image, code, tag, labels, hrefs, disabled flags, and callbacks. Pass `image=\"\"` to hide the art.",
  "categories": [
    "layout",
    "marketing",
    "utility"
  ],
  "deprecated": true,
  "replacedBy": "error-page"
}