{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "typography",
  "type": "registry:ui",
  "title": "Typography",
  "description": "Token-backed Typography, Heading, and Text primitives for semantic headings and application copy.",
  "dependencies": [],
  "devDependencies": [],
  "registryDependencies": [
    "https://components.dethink.co.uk/r/dethink-base.json"
  ],
  "files": [
    {
      "path": "packages/components/src/components/typography/typography.tsx",
      "type": "registry:file",
      "target": "~/components/dethink/components/typography/typography.tsx",
      "content": "import {\n  createElement,\n  forwardRef,\n  type HTMLAttributes,\n  type ReactNode,\n} from \"react\";\nimport { cn } from \"../../utils/cn\";\n\nexport type TypographyElement =\n  \"p\" | \"span\" | \"div\" | \"small\" | \"strong\" | \"em\" | \"label\" | \"figcaption\";\n\nexport type TypographyVariant =\n  \"display\" | \"heading\" | \"title\" | \"subtitle\" | \"body\" | \"caption\" | \"label\";\n\nexport type TypographySize =\n  \"xs\" | \"sm\" | \"md\" | \"lg\" | \"xl\" | \"2xl\" | \"3xl\" | \"4xl\";\n\nexport type TypographyTone =\n  | \"default\"\n  | \"muted\"\n  | \"subtle\"\n  | \"primary\"\n  | \"success\"\n  | \"warning\"\n  | \"destructive\";\n\nexport type TypographyWeight = \"regular\" | \"medium\" | \"semibold\" | \"bold\";\nexport type TypographyAlign = \"start\" | \"center\" | \"end\" | \"justify\";\nexport type HeadingLevel = 1 | 2 | 3 | 4 | 5 | 6;\nexport type HeadingVisualLevel = HeadingLevel;\nexport type TypographyLineClamp = 1 | 2 | 3 | 4 | 5 | 6;\n\nexport interface TypographyProps extends HTMLAttributes<HTMLElement> {\n  as?: TypographyElement;\n  align?: TypographyAlign;\n  children?: ReactNode;\n  lineClamp?: TypographyLineClamp;\n  size?: TypographySize;\n  tone?: TypographyTone;\n  truncate?: boolean;\n  variant?: TypographyVariant;\n  weight?: TypographyWeight;\n}\n\nexport interface HeadingProps extends HTMLAttributes<HTMLHeadingElement> {\n  align?: TypographyAlign;\n  children?: ReactNode;\n  level?: HeadingLevel;\n  lineClamp?: TypographyLineClamp;\n  tone?: Extract<\n    TypographyTone,\n    \"default\" | \"muted\" | \"subtle\" | \"primary\" | \"destructive\"\n  >;\n  truncate?: boolean;\n  visualLevel?: HeadingVisualLevel;\n}\n\nexport type TextElement =\n  \"p\" | \"span\" | \"div\" | \"small\" | \"label\" | \"strong\" | \"em\";\nexport type TextSize = \"xs\" | \"sm\" | \"md\" | \"lg\" | \"xl\";\n\nexport interface TextProps extends HTMLAttributes<HTMLElement> {\n  as?: TextElement;\n  align?: TypographyAlign;\n  children?: ReactNode;\n  htmlFor?: string;\n  lineClamp?: TypographyLineClamp;\n  size?: TextSize;\n  tone?: TypographyTone;\n  truncate?: boolean;\n  weight?: TypographyWeight;\n}\n\nconst typographyBaseClasses = \"min-w-0 max-w-full font-sans text-foreground\";\n\nconst typographyVariantClasses: Record<TypographyVariant, string> = {\n  display: \"font-heading text-4xl font-semibold leading-tight\",\n  heading: \"font-heading text-2xl font-semibold leading-tight\",\n  title: \"font-heading text-lg font-semibold leading-snug\",\n  subtitle: \"text-base font-medium leading-6\",\n  body: \"text-base font-normal leading-7\",\n  caption: \"text-xs font-normal leading-5\",\n  label: \"text-sm font-medium leading-none\",\n};\n\nconst typographySizeClasses: Record<TypographySize, string> = {\n  xs: \"text-xs leading-5\",\n  sm: \"text-sm leading-6\",\n  md: \"text-base leading-7\",\n  lg: \"text-lg leading-8\",\n  xl: \"text-xl leading-8\",\n  \"2xl\": \"text-2xl leading-tight\",\n  \"3xl\": \"text-3xl leading-tight\",\n  \"4xl\": \"text-4xl leading-tight\",\n};\n\nconst typographyToneClasses: Record<TypographyTone, string> = {\n  default: \"text-foreground\",\n  muted: \"text-muted-foreground\",\n  subtle: \"text-muted-foreground/80\",\n  primary: \"text-primary\",\n  success: \"text-success\",\n  warning: \"text-warning\",\n  destructive: \"text-destructive\",\n};\n\nconst typographyWeightClasses: Record<TypographyWeight, string> = {\n  regular: \"font-normal\",\n  medium: \"font-medium\",\n  semibold: \"font-semibold\",\n  bold: \"font-bold\",\n};\n\nconst typographyAlignClasses: Record<TypographyAlign, string> = {\n  start: \"text-start\",\n  center: \"text-center\",\n  end: \"text-end\",\n  justify: \"text-justify\",\n};\n\nconst headingVisualLevelClasses: Record<HeadingVisualLevel, string> = {\n  1: \"font-heading text-4xl font-semibold leading-tight\",\n  2: \"font-heading text-3xl font-semibold leading-tight\",\n  3: \"font-heading text-2xl font-semibold leading-tight\",\n  4: \"font-heading text-xl font-semibold leading-snug\",\n  5: \"font-heading text-lg font-semibold leading-snug\",\n  6: \"font-heading text-base font-semibold leading-6\",\n};\n\nconst headingToneClasses: Record<NonNullable<HeadingProps[\"tone\"]>, string> = {\n  default: \"text-foreground\",\n  muted: \"text-muted-foreground\",\n  subtle: \"text-muted-foreground/80\",\n  primary: \"text-primary\",\n  destructive: \"text-destructive\",\n};\n\nconst textSizeClasses: Record<TextSize, string> = {\n  xs: \"text-xs leading-5\",\n  sm: \"text-sm leading-6\",\n  md: \"text-base leading-7\",\n  lg: \"text-lg leading-8\",\n  xl: \"text-xl leading-8\",\n};\n\nconst lineClampClasses: Record<TypographyLineClamp, string> = {\n  1: \"line-clamp-1\",\n  2: \"line-clamp-2\",\n  3: \"line-clamp-3\",\n  4: \"line-clamp-4\",\n  5: \"line-clamp-5\",\n  6: \"line-clamp-6\",\n};\n\nconst headingElements: Record<HeadingLevel, `h${HeadingLevel}`> = {\n  1: \"h1\",\n  2: \"h2\",\n  3: \"h3\",\n  4: \"h4\",\n  5: \"h5\",\n  6: \"h6\",\n};\n\nfunction getOverflowClass({\n  lineClamp,\n  truncate,\n}: {\n  lineClamp?: TypographyLineClamp;\n  truncate?: boolean;\n}) {\n  if (lineClamp !== undefined) {\n    return lineClampClasses[lineClamp];\n  }\n\n  return truncate ? \"truncate\" : undefined;\n}\n\nexport function typographyClassNames({\n  align = \"start\",\n  className,\n  lineClamp,\n  size,\n  tone = \"default\",\n  truncate = false,\n  variant = \"body\",\n  weight,\n}: Pick<\n  TypographyProps,\n  | \"align\"\n  | \"className\"\n  | \"lineClamp\"\n  | \"size\"\n  | \"tone\"\n  | \"truncate\"\n  | \"variant\"\n  | \"weight\"\n> = {}) {\n  return cn(\n    typographyBaseClasses,\n    typographyVariantClasses[variant],\n    size ? typographySizeClasses[size] : undefined,\n    typographyToneClasses[tone],\n    weight ? typographyWeightClasses[weight] : undefined,\n    typographyAlignClasses[align],\n    getOverflowClass({ lineClamp, truncate }),\n    className,\n  );\n}\n\nexport function headingClassNames({\n  align = \"start\",\n  className,\n  lineClamp,\n  tone = \"default\",\n  truncate = false,\n  visualLevel = 2,\n}: Pick<\n  HeadingProps,\n  \"align\" | \"className\" | \"lineClamp\" | \"tone\" | \"truncate\" | \"visualLevel\"\n> = {}) {\n  return cn(\n    typographyBaseClasses,\n    headingVisualLevelClasses[visualLevel],\n    headingToneClasses[tone],\n    typographyAlignClasses[align],\n    getOverflowClass({ lineClamp, truncate }),\n    className,\n  );\n}\n\nexport function textClassNames({\n  align = \"start\",\n  className,\n  lineClamp,\n  size = \"md\",\n  tone = \"default\",\n  truncate = false,\n  weight = \"regular\",\n}: Pick<\n  TextProps,\n  \"align\" | \"className\" | \"lineClamp\" | \"size\" | \"tone\" | \"truncate\" | \"weight\"\n> = {}) {\n  return cn(\n    typographyBaseClasses,\n    textSizeClasses[size],\n    typographyToneClasses[tone],\n    typographyWeightClasses[weight],\n    typographyAlignClasses[align],\n    getOverflowClass({ lineClamp, truncate }),\n    className,\n  );\n}\n\nexport const Typography = forwardRef<HTMLElement, TypographyProps>(\n  (\n    {\n      align = \"start\",\n      as = \"p\",\n      children,\n      className,\n      lineClamp,\n      size,\n      tone = \"default\",\n      truncate = false,\n      variant = \"body\",\n      weight,\n      ...props\n    },\n    ref,\n  ) =>\n    createElement(\n      as,\n      {\n        ...props,\n        ref,\n        \"data-slot\": \"typography\",\n        \"data-align\": align,\n        \"data-line-clamp\": lineClamp,\n        \"data-size\": size,\n        \"data-tone\": tone,\n        \"data-truncate\":\n          truncate && lineClamp === undefined ? \"true\" : undefined,\n        \"data-variant\": variant,\n        \"data-weight\": weight,\n        className: typographyClassNames({\n          align,\n          className,\n          lineClamp,\n          size,\n          tone,\n          truncate,\n          variant,\n          weight,\n        }),\n      },\n      children,\n    ),\n);\n\nTypography.displayName = \"Typography\";\n\nexport const Heading = forwardRef<HTMLHeadingElement, HeadingProps>(\n  (\n    {\n      align = \"start\",\n      children,\n      className,\n      level = 2,\n      lineClamp,\n      tone = \"default\",\n      truncate = false,\n      visualLevel = level,\n      ...props\n    },\n    ref,\n  ) =>\n    createElement(\n      headingElements[level],\n      {\n        ...props,\n        ref,\n        \"data-slot\": \"heading\",\n        \"data-align\": align,\n        \"data-level\": level,\n        \"data-line-clamp\": lineClamp,\n        \"data-tone\": tone,\n        \"data-truncate\":\n          truncate && lineClamp === undefined ? \"true\" : undefined,\n        \"data-visual-level\": visualLevel,\n        className: headingClassNames({\n          align,\n          className,\n          lineClamp,\n          tone,\n          truncate,\n          visualLevel,\n        }),\n      },\n      children,\n    ),\n);\n\nHeading.displayName = \"Heading\";\n\nexport const Text = forwardRef<HTMLElement, TextProps>(\n  (\n    {\n      align = \"start\",\n      as = \"p\",\n      children,\n      className,\n      lineClamp,\n      size = \"md\",\n      tone = \"default\",\n      truncate = false,\n      weight = \"regular\",\n      ...props\n    },\n    ref,\n  ) =>\n    createElement(\n      as,\n      {\n        ...props,\n        ref,\n        \"data-slot\": \"text\",\n        \"data-align\": align,\n        \"data-line-clamp\": lineClamp,\n        \"data-size\": size,\n        \"data-tone\": tone,\n        \"data-truncate\":\n          truncate && lineClamp === undefined ? \"true\" : undefined,\n        \"data-weight\": weight,\n        className: textClassNames({\n          align,\n          className,\n          lineClamp,\n          size,\n          tone,\n          truncate,\n          weight,\n        }),\n      },\n      children,\n    ),\n);\n\nText.displayName = \"Text\";\n"
    },
    {
      "path": "packages/components/src/components/typography/index.ts",
      "type": "registry:file",
      "target": "~/components/dethink/components/typography/index.ts",
      "content": "export {\n  Heading,\n  Text,\n  Typography,\n  headingClassNames,\n  textClassNames,\n  typographyClassNames,\n  type HeadingLevel,\n  type HeadingProps,\n  type HeadingVisualLevel,\n  type TextElement,\n  type TextProps,\n  type TextSize,\n  type TypographyAlign,\n  type TypographyElement,\n  type TypographyLineClamp,\n  type TypographyProps,\n  type TypographySize,\n  type TypographyTone,\n  type TypographyVariant,\n  type TypographyWeight,\n} from \"./typography\";\n"
    },
    {
      "path": "packages/components/src/utils/cn.ts",
      "type": "registry:file",
      "target": "~/components/dethink/utils/cn.ts",
      "content": "import { clsx, type ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]) {\n  return twMerge(clsx(inputs));\n}\n"
    }
  ]
}
