{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "issue-report-form",
  "version": "1.0.7",
  "category": "form",
  "meta": {
    "preview": "https://ui.manifest.build/previews/issue-report-form.png",
    "version": "1.0.7",
    "changelog": {
      "1.0.0": "Initial release with categories, impact levels and file attachments",
      "1.0.1": "Added aria-label to file removal button for screen reader accessibility",
      "1.0.3": "Added comprehensive JSDoc documentation",
      "1.0.4": "Updated Props interface with decorative header and sub-parameter JSDoc documentation",
      "1.0.5": "Fixed defensive property access to handle empty objects and null values",
      "1.0.6": "Removed default content data - component only renders explicitly provided data",
      "1.0.7": "Show demo data when rendered without props"
    }
  },
  "changelog": {
    "1.0.0": "Initial release with categories, impact levels and file attachments",
    "1.0.1": "Added aria-label to file removal button for screen reader accessibility",
    "1.0.3": "Added comprehensive JSDoc documentation",
    "1.0.4": "Updated Props interface with decorative header and sub-parameter JSDoc documentation",
    "1.0.5": "Fixed defensive property access to handle empty objects and null values",
    "1.0.6": "Removed default content data - component only renders explicitly provided data",
    "1.0.7": "Show demo data when rendered without props"
  },
  "title": "Issue Report Form",
  "author": "MNFST, Inc",
  "description": "A compact issue reporting form for team members with categories, impact/urgency levels, and file attachments.",
  "dependencies": [
    "lucide-react"
  ],
  "registryDependencies": [
    "button",
    "input",
    "label",
    "select"
  ],
  "files": [
    {
      "path": "registry/form/issue-report-form.tsx",
      "content": "'use client'\n\nimport { Button } from '@/components/ui/button'\nimport { Input } from '@/components/ui/input'\nimport { Label } from '@/components/ui/label'\nimport {\n  Select,\n  SelectContent,\n  SelectItem,\n  SelectTrigger,\n  SelectValue\n} from '@/components/ui/select'\nimport { cn } from '@/lib/utils'\nimport { demoIssueReportFormData } from './demo/form'\nimport { ChevronDown, ChevronUp, Paperclip, Send, X } from 'lucide-react'\nimport { useRef, useState } from 'react'\n\n\n/**\n * ═══════════════════════════════════════════════════════════════════════════\n * IssueReportFormProps\n * ═══════════════════════════════════════════════════════════════════════════\n *\n * Props for the IssueReportForm component for IT support, help desk, or\n * internal ticketing systems.\n */\nexport interface IssueReportFormProps {\n  data?: {\n    /** Form title displayed at the top. */\n    title?: string\n    /** List of team options for the dropdown. */\n    teams?: string[]\n    /** List of location options. */\n    locations?: string[]\n    /** Category to subcategory mapping. */\n    categories?: Record<string, string[]>\n    /** Impact level options. */\n    impacts?: { value: string; label: string }[]\n    /** Urgency level options. */\n    urgencies?: { value: string; label: string }[]\n    /** Frequency options. */\n    frequencies?: { value: string; label: string }[]\n    /** Pre-defined actions user may have tried. */\n    attemptedActions?: string[]\n  }\n  actions?: {\n    /** Called when the form is submitted. */\n    onSubmit?: (formData: IssueFormData) => void\n  }\n  appearance?: {\n    /**\n     * Whether to display the title.\n     * @default true\n     */\n    showTitle?: boolean\n    /**\n     * Use compact layout.\n     * @default true\n     */\n    compactMode?: boolean\n  }\n}\n\n/**\n * Data structure representing an issue report submission.\n * @interface IssueFormData\n * @property {string} declarantName - Name of the person reporting the issue\n * @property {string} email - Contact email for follow-up\n * @property {string} team - Department or team affected\n * @property {string} location - Office location\n * @property {string} office - Specific office or area identifier\n * @property {string} workstation - Machine or workstation identifier\n * @property {string} category - Main issue category (e.g., 'Software', 'Hardware')\n * @property {string} subcategory - Specific subcategory within the main category\n * @property {string} issueTitle - Brief summary of the issue\n * @property {string} description - Detailed description of the problem\n * @property {string} impact - Impact level (critical, high, medium, low)\n * @property {string} urgency - How urgent the fix is needed\n * @property {string} frequency - How often the issue occurs\n * @property {string} startDate - When the issue first occurred\n * @property {string[]} attemptedActions - List of troubleshooting actions already tried\n * @property {File[]} attachments - Supporting files (screenshots, logs, etc.)\n * @property {string} additionalComments - Any extra information\n */\nexport interface IssueFormData {\n  declarantName?: string\n  email?: string\n  team?: string\n  location?: string\n  office?: string\n  workstation?: string\n  category?: string\n  subcategory?: string\n  issueTitle?: string\n  description?: string\n  impact?: string\n  urgency?: string\n  frequency?: string\n  startDate?: string\n  attemptedActions?: string[]\n  attachments?: File[]\n  additionalComments?: string\n}\n\n/**\n * A comprehensive issue reporting form for IT support, help desk, or internal ticketing systems.\n * Includes categorization, impact assessment, and file attachments.\n *\n * Features:\n * - Reporter information (name, email)\n * - Team and location selection\n * - Category with dynamic subcategories\n * - Impact, urgency, and frequency assessment\n * - Collapsible sections for detailed context\n * - Pre-defined troubleshooting actions checklist\n * - Multiple file attachment support\n * - Office/workstation identification\n *\n * @component\n * @example\n * ```tsx\n * <IssueReportForm\n *   data={{\n *     title: \"Report a Problem\",\n *     teams: [\"Engineering\", \"Design\", \"Product\"],\n *     categories: {\n *       \"Software\": [\"Email\", \"Browser\", \"VPN\"],\n *       \"Hardware\": [\"Computer\", \"Monitor\", \"Keyboard\"]\n *     }\n *   }}\n *   actions={{\n *     onSubmit: (data) => console.log(\"Issue reported:\", data)\n *   }}\n *   appearance={{ showTitle: true, compactMode: true }}\n * />\n * ```\n */\nexport function IssueReportForm({\n  data,\n  actions,\n  appearance\n}: IssueReportFormProps) {\n  const resolved: NonNullable<IssueReportFormProps['data']> = data ?? demoIssueReportFormData\n  const title = resolved.title\n  const teams = resolved.teams ?? []\n  const locations = resolved.locations ?? []\n  const categories = resolved.categories ?? {}\n  const impacts = resolved.impacts ?? []\n  const urgencies = resolved.urgencies ?? []\n  const frequencies = resolved.frequencies ?? []\n  const attemptedActions = resolved.attemptedActions ?? []\n  const { onSubmit } = actions ?? {}\n  const { showTitle = true } = appearance ?? {}\n\n  const [formData, setFormData] = useState<IssueFormData>({\n    declarantName: '',\n    email: '',\n    team: '',\n    location: '',\n    office: '',\n    workstation: '',\n    category: '',\n    subcategory: '',\n    issueTitle: '',\n    description: '',\n    impact: '',\n    urgency: '',\n    frequency: '',\n    startDate: '',\n    attemptedActions: [],\n    attachments: [],\n    additionalComments: ''\n  })\n\n  const [expandedSection, setExpandedSection] = useState<\n    'details' | 'context' | null\n  >('details')\n  const fileInputRef = useRef<HTMLInputElement>(null)\n\n  const subcategories = formData.category\n    ? categories[formData.category] || []\n    : []\n\n  const updateField = <K extends keyof IssueFormData>(\n    field: K,\n    value: IssueFormData[K]\n  ) => {\n    setFormData((prev) => ({ ...prev, [field]: value }))\n  }\n\n  const handleCategoryChange = (value: string) => {\n    setFormData((prev) => ({ ...prev, category: value, subcategory: '' }))\n  }\n\n  const toggleAttemptedAction = (action: string) => {\n    setFormData((prev) => {\n      const currentActions = prev.attemptedActions ?? []\n      return {\n        ...prev,\n        attemptedActions: currentActions.includes(action)\n          ? currentActions.filter((a) => a !== action)\n          : [...currentActions, action]\n      }\n    })\n  }\n\n  const handleFileSelect = (e: React.ChangeEvent<HTMLInputElement>) => {\n    const files = Array.from(e.target.files || [])\n    setFormData((prev) => ({\n      ...prev,\n      attachments: [...(prev.attachments ?? []), ...files]\n    }))\n    if (fileInputRef.current) fileInputRef.current.value = ''\n  }\n\n  const removeFile = (index: number) => {\n    setFormData((prev) => ({\n      ...prev,\n      attachments: (prev.attachments ?? []).filter((_, i) => i !== index)\n    }))\n  }\n\n  const handleSubmit = () => {\n    onSubmit?.(formData)\n  }\n\n  const toggleSection = (section: 'details' | 'context') => {\n    setExpandedSection((prev) => (prev === section ? null : section))\n  }\n\n  return (\n    <div className=\"w-full bg-card rounded-xl p-4\">\n      {showTitle && title && (\n        <div className=\"flex items-center gap-2 mb-4\">\n          <h2 className=\"text-lg font-semibold text-foreground\">{title}</h2>\n        </div>\n      )}\n\n      <div className=\"space-y-3\">\n        {/* Declarant Info - Always visible */}\n        <div className=\"grid grid-cols-2 gap-2\">\n          <div>\n            <Label className=\"text-xs text-muted-foreground mb-1 block\">\n              Name\n            </Label>\n            <Input\n              placeholder=\"Your name\"\n              value={formData.declarantName}\n              onChange={(e) => updateField('declarantName', e.target.value)}\n              className=\"h-9 text-sm\"\n            />\n          </div>\n          <div>\n            <Label className=\"text-xs text-muted-foreground mb-1 block\">\n              Email\n            </Label>\n            <Input\n              type=\"email\"\n              placeholder=\"your@email.com\"\n              value={formData.email}\n              onChange={(e) => updateField('email', e.target.value)}\n              className=\"h-9 text-sm\"\n            />\n          </div>\n        </div>\n\n        {/* Team, Location, Category, Subcategory - 2 cols on mobile, 4 on desktop */}\n        <div className=\"grid grid-cols-2 md:grid-cols-4 gap-2\">\n          <div className=\"min-w-0\">\n            <Label className=\"text-xs text-muted-foreground mb-1 block\">\n              Team\n            </Label>\n            <Select\n              value={formData.team}\n              onValueChange={(v) => updateField('team', v)}\n            >\n              <SelectTrigger className=\"h-9 text-sm w-full\">\n                <SelectValue placeholder=\"Select\" />\n              </SelectTrigger>\n              <SelectContent>\n                {teams.map((team) => (\n                  <SelectItem key={team} value={team}>\n                    {team}\n                  </SelectItem>\n                ))}\n              </SelectContent>\n            </Select>\n          </div>\n          <div className=\"min-w-0\">\n            <Label className=\"text-xs text-muted-foreground mb-1 block\">\n              Location\n            </Label>\n            <Select\n              value={formData.location}\n              onValueChange={(v) => updateField('location', v)}\n            >\n              <SelectTrigger className=\"h-9 text-sm w-full\">\n                <SelectValue placeholder=\"Select\" />\n              </SelectTrigger>\n              <SelectContent>\n                {locations.map((loc) => (\n                  <SelectItem key={loc} value={loc}>\n                    {loc}\n                  </SelectItem>\n                ))}\n              </SelectContent>\n            </Select>\n          </div>\n          <div className=\"min-w-0\">\n            <Label className=\"text-xs text-muted-foreground mb-1 block\">\n              Category\n            </Label>\n            <Select\n              value={formData.category}\n              onValueChange={handleCategoryChange}\n            >\n              <SelectTrigger className=\"h-9 text-sm w-full\">\n                <SelectValue placeholder=\"Select\" />\n              </SelectTrigger>\n              <SelectContent>\n                {Object.keys(categories).map((cat) => (\n                  <SelectItem key={cat} value={cat}>\n                    {cat}\n                  </SelectItem>\n                ))}\n              </SelectContent>\n            </Select>\n          </div>\n          <div className=\"min-w-0\">\n            <Label className=\"text-xs text-muted-foreground mb-1 block\">\n              Subcategory\n            </Label>\n            <Select\n              value={formData.subcategory}\n              onValueChange={(v) => updateField('subcategory', v)}\n              disabled={!formData.category}\n            >\n              <SelectTrigger className=\"h-9 text-sm w-full\">\n                <SelectValue\n                  placeholder={formData.category ? 'Select' : 'Pick category'}\n                />\n              </SelectTrigger>\n              <SelectContent>\n                {subcategories.map((sub) => (\n                  <SelectItem key={sub} value={sub}>\n                    {sub}\n                  </SelectItem>\n                ))}\n              </SelectContent>\n            </Select>\n          </div>\n        </div>\n\n        {/* Issue Title */}\n        <div>\n          <Label className=\"text-xs text-muted-foreground mb-1 block\">\n            Issue Title\n          </Label>\n          <Input\n            placeholder=\"Summarize your issue in a few words\"\n            value={formData.issueTitle}\n            onChange={(e) => updateField('issueTitle', e.target.value)}\n            className=\"h-9 text-sm\"\n          />\n        </div>\n\n        {/* Description */}\n        <div>\n          <Label className=\"text-xs text-muted-foreground mb-1 block\">\n            Description\n          </Label>\n          <textarea\n            placeholder=\"Describe the issue in detail...\"\n            value={formData.description}\n            onChange={(e) => updateField('description', e.target.value)}\n            className=\"w-full px-3 py-2 text-sm border rounded-lg resize-none focus:outline-none focus:border-primary bg-background min-h-[80px]\"\n          />\n        </div>\n\n        {/* Collapsible: Details Section */}\n        <div className=\"border rounded-lg overflow-hidden\">\n          <button\n            onClick={() => toggleSection('details')}\n            className=\"w-full px-3 py-2 flex items-center justify-between text-sm font-medium text-foreground bg-muted/50 hover:bg-muted transition-colors\"\n          >\n            <span>Impact & Urgency</span>\n            {expandedSection === 'details' ? (\n              <ChevronUp className=\"h-4 w-4 text-muted-foreground\" />\n            ) : (\n              <ChevronDown className=\"h-4 w-4 text-muted-foreground\" />\n            )}\n          </button>\n          <div\n            className={cn(\n              'overflow-hidden transition-all duration-200',\n              expandedSection === 'details' ? 'max-h-[500px] p-3' : 'max-h-0'\n            )}\n          >\n            <div className=\"grid grid-cols-2 md:grid-cols-4 gap-2\">\n              <div className=\"min-w-0\">\n                <Label className=\"text-xs text-muted-foreground mb-1 block\">\n                  Impact\n                </Label>\n                <Select\n                  value={formData.impact}\n                  onValueChange={(v) => updateField('impact', v)}\n                >\n                  <SelectTrigger className=\"h-9 text-sm w-full\">\n                    <SelectValue placeholder=\"Impact\" />\n                  </SelectTrigger>\n                  <SelectContent>\n                    {impacts.map((imp) => (\n                      <SelectItem key={imp.value} value={imp.value}>\n                        {imp.label}\n                      </SelectItem>\n                    ))}\n                  </SelectContent>\n                </Select>\n              </div>\n              <div className=\"min-w-0\">\n                <Label className=\"text-xs text-muted-foreground mb-1 block\">\n                  Urgency\n                </Label>\n                <Select\n                  value={formData.urgency}\n                  onValueChange={(v) => updateField('urgency', v)}\n                >\n                  <SelectTrigger className=\"h-9 text-sm w-full\">\n                    <SelectValue placeholder=\"Urgency\" />\n                  </SelectTrigger>\n                  <SelectContent>\n                    {urgencies.map((urg) => (\n                      <SelectItem key={urg.value} value={urg.value}>\n                        {urg.label}\n                      </SelectItem>\n                    ))}\n                  </SelectContent>\n                </Select>\n              </div>\n              <div className=\"min-w-0\">\n                <Label className=\"text-xs text-muted-foreground mb-1 block\">\n                  Frequency\n                </Label>\n                <Select\n                  value={formData.frequency}\n                  onValueChange={(v) => updateField('frequency', v)}\n                >\n                  <SelectTrigger className=\"h-9 text-sm w-full\">\n                    <SelectValue placeholder=\"Frequency\" />\n                  </SelectTrigger>\n                  <SelectContent>\n                    {frequencies.map((freq) => (\n                      <SelectItem key={freq.value} value={freq.value}>\n                        {freq.label}\n                      </SelectItem>\n                    ))}\n                  </SelectContent>\n                </Select>\n              </div>\n              <div className=\"min-w-0\">\n                <Label className=\"text-xs text-muted-foreground mb-1 block\">\n                  Start Date\n                </Label>\n                <Input\n                  type=\"date\"\n                  value={formData.startDate}\n                  onChange={(e) => updateField('startDate', e.target.value)}\n                  className=\"h-9 text-sm w-full\"\n                />\n              </div>\n            </div>\n          </div>\n        </div>\n\n        {/* Collapsible: Context Section */}\n        <div className=\"border rounded-lg overflow-hidden\">\n          <button\n            onClick={() => toggleSection('context')}\n            className=\"w-full px-3 py-2 flex items-center justify-between text-sm font-medium text-foreground bg-muted/50 hover:bg-muted transition-colors\"\n          >\n            <span>Additional Context</span>\n            {expandedSection === 'context' ? (\n              <ChevronUp className=\"h-4 w-4 text-muted-foreground\" />\n            ) : (\n              <ChevronDown className=\"h-4 w-4 text-muted-foreground\" />\n            )}\n          </button>\n          <div\n            className={cn(\n              'overflow-hidden transition-all duration-200',\n              expandedSection === 'context' ? 'max-h-[500px] p-3' : 'max-h-0'\n            )}\n          >\n            <div className=\"space-y-3\">\n              <div>\n                <Label className=\"text-xs text-muted-foreground mb-2 block\">\n                  Actions Already Tried\n                </Label>\n                <div className=\"flex flex-wrap gap-1.5\">\n                  {attemptedActions.map((action) => (\n                    <button\n                      key={action}\n                      onClick={() => toggleAttemptedAction(action)}\n                      className={cn(\n                        'px-2 py-1 text-xs rounded-md border transition-colors',\n                        (formData.attemptedActions ?? []).includes(action)\n                          ? 'bg-primary text-primary-foreground border-primary'\n                          : 'bg-background text-foreground border-border hover:border-primary'\n                      )}\n                    >\n                      {action}\n                    </button>\n                  ))}\n                </div>\n              </div>\n\n              <div className=\"grid grid-cols-2 gap-2\">\n                {/* Left column: Office and Workstation stacked */}\n                <div className=\"space-y-2\">\n                  <div>\n                    <Label className=\"text-xs text-muted-foreground mb-1 block\">\n                      Office / Area\n                    </Label>\n                    <Input\n                      placeholder=\"E.g.: Office 3B\"\n                      value={formData.office}\n                      onChange={(e) => updateField('office', e.target.value)}\n                      className=\"h-9 text-sm\"\n                    />\n                  </div>\n                  <div>\n                    <Label className=\"text-xs text-muted-foreground mb-1 block\">\n                      Workstation / Machine\n                    </Label>\n                    <Input\n                      placeholder=\"E.g.: PC-DEV-042\"\n                      value={formData.workstation}\n                      onChange={(e) =>\n                        updateField('workstation', e.target.value)\n                      }\n                      className=\"h-9 text-sm\"\n                    />\n                  </div>\n                </div>\n                {/* Right column: Comments matching height of left column */}\n                <div className=\"flex flex-col\">\n                  <Label className=\"text-xs text-muted-foreground mb-1 block\">\n                    Comments\n                  </Label>\n                  <textarea\n                    placeholder=\"Additional information...\"\n                    value={formData.additionalComments}\n                    onChange={(e) =>\n                      updateField('additionalComments', e.target.value)\n                    }\n                    className=\"flex-1 w-full px-3 py-2 text-sm border rounded-lg resize-none focus:outline-none focus:border-primary bg-background\"\n                  />\n                </div>\n              </div>\n            </div>\n          </div>\n        </div>\n\n        {/* Attachments */}\n        <div>\n          <input\n            ref={fileInputRef}\n            type=\"file\"\n            multiple\n            onChange={handleFileSelect}\n            className=\"hidden\"\n          />\n          {(formData.attachments ?? []).length > 0 && (\n            <div className=\"flex flex-wrap gap-1.5 mb-2\">\n              {(formData.attachments ?? []).map((file, index) => (\n                <div\n                  key={index}\n                  className=\"flex items-center gap-1 px-2 py-1 bg-muted rounded text-xs\"\n                >\n                  <Paperclip className=\"h-3 w-3\" />\n                  <span className=\"max-w-[100px] truncate\">{file.name}</span>\n                  <button\n                    onClick={() => removeFile(index)}\n                    aria-label=\"Remove file\"\n                    className=\"text-muted-foreground hover:text-foreground\"\n                  >\n                    <X className=\"h-3 w-3\" />\n                  </button>\n                </div>\n              ))}\n            </div>\n          )}\n        </div>\n\n        {/* Actions */}\n        <div className=\"flex flex-col sm:flex-row sm:items-center sm:justify-between gap-2 pt-2\">\n          <Button\n            variant=\"outline\"\n            size=\"sm\"\n            onClick={() => fileInputRef.current?.click()}\n            className=\"h-9 w-full sm:w-auto\"\n          >\n            <Paperclip className=\"h-4 w-4 mr-1.5\" />\n            Attach a file\n          </Button>\n          <Button\n            onClick={handleSubmit}\n            size=\"sm\"\n            className=\"h-9 w-full sm:w-auto\"\n          >\n            <Send className=\"h-4 w-4 mr-1.5\" />\n            Submit\n          </Button>\n        </div>\n      </div>\n    </div>\n  )\n}\n",
      "type": "registry:block",
      "target": "components/ui/issue-report-form.tsx"
    },
    {
      "path": "registry/form/demo/form.ts",
      "content": "// Demo data for Form category components\n// This file contains sample data used for component previews and documentation\n\n/**\n * Generate available dates dynamically so the DateTimePicker preview\n * always has clickable dates regardless of when it is viewed.\n */\nfunction generateAvailableDates(): Date[] {\n  const dates: Date[] = [];\n  const now = new Date();\n  // Walk through current and next month, only keeping weekdays (Mon-Fri)\n  for (let m = 0; m <= 1; m++) {\n    for (let d = 1; d <= 28; d += 2) {\n      const date = new Date(now.getFullYear(), now.getMonth() + m, d);\n      const day = date.getDay();\n      if (day !== 0 && day !== 6) {\n        dates.push(date);\n      }\n    }\n  }\n  return dates;\n}\n\nexport const demoContactFormData = {\n  title: 'Get in Touch',\n  subtitle: \"We'd love to hear from you. Fill out the form below.\",\n  submitLabel: 'Send Message',\n}\n\nexport const demoIssueReportFormData = {\n  title: 'Report an Issue',\n  teams: ['Engineering', 'Product', 'Design', 'Marketing', 'Operations'],\n  locations: ['New York - HQ', 'San Francisco', 'London', 'Remote'],\n  categories: {\n    Software: ['Business App', 'Email', 'VPN', 'Browser', 'OS'],\n    Hardware: ['Computer', 'Monitor', 'Keyboard', 'Mouse', 'Printer'],\n    Network: ['Wi-Fi', 'Ethernet', 'VPN Access'],\n    Access: ['Account', 'Permissions', 'Password Reset'],\n  } as Record<string, string[]>,\n  impacts: [\n    { value: 'critical', label: 'Critical - Work stopped' },\n    { value: 'high', label: 'High - Major feature broken' },\n    { value: 'medium', label: 'Medium - Workaround available' },\n    { value: 'low', label: 'Low - Minor inconvenience' },\n  ],\n  urgencies: [\n    { value: 'immediate', label: 'Immediate' },\n    { value: 'today', label: 'Today' },\n    { value: 'this-week', label: 'This week' },\n    { value: 'no-rush', label: 'No rush' },\n  ],\n  frequencies: [\n    { value: 'constant', label: 'Constant' },\n    { value: 'frequent', label: 'Frequent' },\n    { value: 'occasional', label: 'Occasional' },\n    { value: 'once', label: 'Happened once' },\n  ],\n  attemptedActions: [\n    'Restarted the application',\n    'Cleared browser cache',\n    'Restarted computer',\n    'Checked internet connection',\n    'Contacted a colleague',\n  ],\n}\n\nexport const demoDateTimePickerData = {\n  title: 'Select a Date & Time',\n  availableDates: generateAvailableDates(),\n  availableTimeSlots: [\n    '9:00am',\n    '10:00am',\n    '11:30am',\n    '1:00pm',\n    '2:30pm',\n    '4:00pm',\n  ],\n  timezone: 'Eastern Time - US & Canada',\n};\n",
      "type": "registry:lib",
      "target": "components/ui/demo/form.ts"
    }
  ],
  "categories": [
    "form"
  ],
  "type": "registry:block"
}