{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "tag",
  "title": "Tag",
  "description": "Flat marker-yellow tag with ink text.",
  "registryDependencies": [
    "https://frame12.dev/r/frame12-styles.json"
  ],
  "files": [
    {
      "path": "ui/tag.tsx",
      "content": "'use client';\n\nimport * as React from 'react';\n\nexport type SemanticStatus = 'neutral' | 'info' | 'success' | 'warning' | 'danger';\nexport type TagStatus = SemanticStatus;\nexport type TagVariant = 'default' | 'stamp';\n\nexport const STATUS_GLYPHS: Record<SemanticStatus, string | undefined> = {\n  neutral: undefined,\n  info: '[i]',\n  success: '[+]',\n  warning: '[!]',\n  danger: '[×]',\n};\n\nexport const STATUS_SR_LABELS: Record<SemanticStatus, string | undefined> = {\n  neutral: undefined,\n  info: 'Info',\n  success: 'Success',\n  warning: 'Warning',\n  danger: 'Error',\n};\n\nexport function extractTextContent(node: React.ReactNode): string {\n  if (typeof node === 'string' || typeof node === 'number') return String(node);\n  if (Array.isArray(node)) return node.map(extractTextContent).join('');\n  if (\n    React.isValidElement<{\n      children?: React.ReactNode;\n      hidden?: boolean;\n      'aria-hidden'?: boolean | 'true' | 'false';\n    }>(node)\n  ) {\n    if (\n      node.props.hidden ||\n      node.props['aria-hidden'] === true ||\n      node.props['aria-hidden'] === 'true'\n    ) {\n      return '';\n    }\n    return extractTextContent(node.props.children);\n  }\n  return '';\n}\n\nexport const STATUS_SYNONYMS: Record<SemanticStatus, readonly string[]> = {\n  neutral: [],\n  info: ['info', 'information'],\n  success: ['success', 'succeeded'],\n  warning: ['warning', 'warn', 'caution'],\n  danger: ['error', 'danger', 'critical', 'failed'],\n};\n\nexport function startsWithStatusLabel(\n  text: string,\n  label: string,\n  status?: SemanticStatus,\n): boolean {\n  const lowerText = text.trimStart().toLowerCase();\n  const candidates =\n    status && label === STATUS_SR_LABELS[status]\n      ? STATUS_SYNONYMS[status]\n      : [label.toLowerCase()];\n\n  for (const candidate of candidates) {\n    if (!lowerText.startsWith(candidate)) continue;\n    const rest = lowerText.slice(candidate.length);\n    if (rest === '' || !/^\\p{L}/u.test(rest)) return true;\n    if (candidate === 'error' && /^(ed|s)(?!\\p{L})/u.test(rest)) return true;\n    if ((candidate === 'warn' || candidate === 'warning') && /^s(?!\\p{L})/u.test(rest)) {\n      return true;\n    }\n  }\n  return false;\n}\n\nexport interface TagProps extends React.HTMLAttributes<HTMLSpanElement> {\n  variant?: TagVariant;\n  status?: SemanticStatus;\n  glyph?: string | false;\n  srLabel?: string | false;\n  children?: React.ReactNode;\n}\n\nexport interface StampProps extends Omit<TagProps, 'variant'> {\n  children?: React.ReactNode;\n}\n\nexport const Tag = React.forwardRef<HTMLSpanElement, TagProps>(function Tag(\n  { variant = 'default', status, glyph, srLabel, className = '', children, ...rest },\n  ref,\n) {\n  const isStamp = variant === 'stamp';\n  const variantClass = isStamp ? ' f12-tag-stamp' : '';\n  const statusClass = status ? ` f12-status-${status}` : '';\n  const resolvedGlyph =\n    glyph === false\n      ? undefined\n      : glyph !== undefined\n        ? glyph\n        : status\n          ? STATUS_GLYPHS[status]\n          : undefined;\n  const resolvedSrLabel =\n    srLabel === false\n      ? undefined\n      : srLabel !== undefined\n        ? srLabel\n        : status\n          ? STATUS_SR_LABELS[status]\n          : undefined;\n  const childText = extractTextContent(children).trim();\n  const showSrLabel =\n    Boolean(resolvedSrLabel) &&\n    !(childText && resolvedSrLabel && startsWithStatusLabel(childText, resolvedSrLabel, status));\n\n  return (\n    <span\n      ref={ref}\n      className={`f12-tag${variantClass}${statusClass}${className ? ` ${className}` : ''}`}\n      data-variant={isStamp ? 'stamp' : undefined}\n      data-status={status}\n      {...rest}\n    >\n      {resolvedGlyph && (\n        <span className=\"f12-status-glyph\" aria-hidden=\"true\">\n          {resolvedGlyph}\n        </span>\n      )}\n      {showSrLabel && <span className=\"f12-sr-only\">{`${resolvedSrLabel}: `}</span>}\n      {children}\n    </span>\n  );\n});\n\nexport const Stamp = React.forwardRef<HTMLSpanElement, StampProps>(function Stamp(props, ref) {\n  return <Tag ref={ref} {...props} variant=\"stamp\" />;\n});\n",
      "type": "registry:ui",
      "target": "components/frame12/tag.tsx"
    }
  ],
  "type": "registry:ui"
}