{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "data-state-panel",
  "title": "Data State Panel",
  "description": "Data State Panel from the Get IT Done design system.",
  "dependencies": [
    "lucide-react@^0.379.0"
  ],
  "registryDependencies": [
    "https://zero-design.itdone.de/r/button.json",
    "https://zero-design.itdone.de/r/edge.json",
    "https://zero-design.itdone.de/r/labels-context.json",
    "https://zero-design.itdone.de/r/utils.json",
    "https://zero-design.itdone.de/r/theme.json"
  ],
  "files": [
    {
      "path": "registry/ui/data-state-panel.tsx",
      "content": "'use client';\n\nimport { AlertCircle, RefreshCw } from 'lucide-react';\nimport { forwardRef, type HTMLAttributes, type ReactNode } from 'react';\n\nimport { cn } from '@/lib/utils';\nimport { Button } from '@/components/ui/button';\nimport { useEdge } from '@/components/ui/edge';\nimport { useLabels } from '@/components/ui/labels-context';\n\n// Skeleton bar for loading layouts of data components (semantic/overlay/skeleton/default).\nconst SkeletonBar = forwardRef<HTMLSpanElement, HTMLAttributes<HTMLSpanElement>>(({ className, ...props }, ref) => (\n  <span\n    ref={ref}\n    aria-hidden=\"true\"\n    className={cn('block h-3 w-full animate-pulse rounded-item bg-overlay-skeleton-default motion-reduce:animate-none', className)}\n    {...props}\n  />\n));\nSkeletonBar.displayName = 'SkeletonBar';\n\nexport interface DataStatePanelProps extends Omit<HTMLAttributes<HTMLDivElement>, 'title'> {\n  kind: 'empty' | 'error';\n  title: ReactNode;\n  description?: ReactNode;\n  icon?: ReactNode;\n  // Primary action for the empty state (e.g. \"Log time\").\n  action?: ReactNode;\n  // Error state: renders a \"Try again\" button.\n  onRetry?: () => void;\n  // Deprecated: use retryText.\n  retryLabel?: string;\n  retryText?: string;\n  // Dashed outline (empty) or destructive outline (error) around the panel.\n  outlined?: boolean;\n}\n\n// Shared empty and error body for data components (calendar grids, boards, lists, cards).\nconst DataStatePanel = forwardRef<HTMLDivElement, DataStatePanelProps>(\n  ({ className, kind, title, description, icon, action, onRetry, retryLabel: retryLabelProp, retryText, outlined = false, ...props }, ref) => {\n    const l = useLabels();\n    const retryLabel = retryText ?? retryLabelProp ?? l.tryAgain;\n    const isError = kind === 'error';\n    const edge = useEdge();\n    return (\n      <div\n        ref={ref}\n        role={isError ? 'alert' : 'status'}\n        data-state={kind}\n        className={cn(\n          'flex flex-col items-center justify-center gap-2 px-6 py-8 text-center',\n          outlined && 'rounded-card border border-solid',\n          outlined && (isError ? 'border-border-destructive' : cn('border-dashed', edge)),\n          className,\n        )}\n        {...props}\n      >\n        <span aria-hidden=\"true\" className={cn('flex h-icon-md w-icon-md items-center justify-center', isError ? 'text-icon-destructive' : 'text-icon-subtle')}>\n          {icon ?? (isError ? <AlertCircle className=\"h-icon-md w-icon-md\" /> : null)}\n        </span>\n        <p className={cn('typography-ui-medium', isError ? 'text-text-destructive' : 'text-foreground')}>{title}</p>\n        {description ? <p className=\"typography-text-extra-small max-w-reading text-muted-foreground\">{description}</p> : null}\n        {isError && onRetry ? (\n          <Button type=\"button\" variant=\"outline\" size=\"control-sm\" onClick={onRetry}>\n            <RefreshCw aria-hidden=\"true\" className=\"h-icon-sm w-icon-sm\" />\n            {retryLabel}\n          </Button>\n        ) : null}\n        {!isError ? action : null}\n      </div>\n    );\n  },\n);\nDataStatePanel.displayName = 'DataStatePanel';\n\nexport { DataStatePanel, SkeletonBar };\n",
      "type": "registry:ui"
    }
  ],
  "type": "registry:ui"
}