{"$schema":"https:\/\/ui.particle.academy\/schema\/registry-item.json","name":"security-txt-editor","type":"registry:ui","title":"SecurityTxtEditor","description":"RFC 9116 security.txt editor \u2014 required Contact + a future Expires, with inline validation.","package":"fancy-x-files-ui","dependencies":["@particle-academy\/react-fancy"],"registryDependencies":["model.js","validate.js"],"files":[{"path":"components\/fancy\/security-txt-editor\/SecurityTxtEditor.tsx","content":"import { Field, Input } from \"@particle-academy\/react-fancy\";\r\nimport type { SecurityTxtModel } from \"..\/model.js\";\r\nimport { validateSecurityTxt } from \"..\/validate.js\";\r\nimport { IssueList, Section, StringList } from \".\/internal.js\";\r\n\r\nexport interface SecurityTxtEditorProps {\r\n  value: SecurityTxtModel;\r\n  onChange: (next: SecurityTxtModel) => void;\r\n  hideIssues?: boolean;\r\n  className?: string;\r\n}\r\n\r\n\/**\r\n * Controlled security.txt editor (RFC 9116). Contact is required (one or more\r\n * mailto:\/https: URIs) and Expires must be a future date \u2014 surfaced both as a\r\n * date input and inline issues from {@link validateSecurityTxt}.\r\n *\/\r\nexport function SecurityTxtEditor({\r\n  value,\r\n  onChange,\r\n  hideIssues,\r\n  className,\r\n}: SecurityTxtEditorProps) {\r\n  const issues = validateSecurityTxt(value);\r\n  const patch = (next: Partial<SecurityTxtModel>) =>\r\n    onChange({ ...value, ...next });\r\n\r\n  \/\/ <input type=\"datetime-local\"> wants `YYYY-MM-DDTHH:mm`; tolerate a stored\r\n  \/\/ ISO string with seconds\/zone by trimming to minutes for the control.\r\n  const expiresLocal = value.expires ? value.expires.slice(0, 16) : \"\";\r\n\r\n  return (\r\n    <div className={className} data-x-editor=\"securityTxt\">\r\n      <Section title=\"Contact (required)\" handle=\"security-contact\">\r\n        <StringList\r\n          handle=\"security-contact\"\r\n          values={value.contact}\r\n          onChange={(contact) => patch({ contact })}\r\n          placeholder=\"mailto:security@example.com\"\r\n        \/>\r\n      <\/Section>\r\n\r\n      <Section title=\"Expires (required, future)\" handle=\"security-expires\">\r\n        <Field description=\"Must be a date\/time in the future.\">\r\n          <input\r\n            type=\"datetime-local\"\r\n            value={expiresLocal}\r\n            onChange={(e) =>\r\n              patch({\r\n                expires: e.target.value\r\n                  ? `${e.target.value}:00Z`\r\n                  : \"\",\r\n              })\r\n            }\r\n            data-x-input=\"security-expires\"\r\n            style={{\r\n              padding: \"0.4rem 0.6rem\",\r\n              borderRadius: \"0.4rem\",\r\n              border: \"1px solid var(--rf-border, #e5e7eb)\",\r\n            }}\r\n          \/>\r\n        <\/Field>\r\n      <\/Section>\r\n\r\n      <Section title=\"Optional fields\" handle=\"security-optional\">\r\n        <Input\r\n          label=\"Encryption\"\r\n          value={value.encryption ?? \"\"}\r\n          onValueChange={(v) => patch({ encryption: v || undefined })}\r\n          placeholder=\"https:\/\/example.com\/pgp-key.txt\"\r\n          data-x-input=\"security-encryption\"\r\n        \/>\r\n        <Input\r\n          label=\"Acknowledgments\"\r\n          value={value.acknowledgments ?? \"\"}\r\n          onValueChange={(v) => patch({ acknowledgments: v || undefined })}\r\n          placeholder=\"https:\/\/example.com\/hall-of-fame\"\r\n          data-x-input=\"security-acknowledgments\"\r\n        \/>\r\n        <Input\r\n          label=\"Preferred-Languages\"\r\n          value={value.preferredLanguages ?? \"\"}\r\n          onValueChange={(v) => patch({ preferredLanguages: v || undefined })}\r\n          placeholder=\"en, fr\"\r\n          data-x-input=\"security-languages\"\r\n        \/>\r\n        <Input\r\n          label=\"Canonical\"\r\n          value={value.canonical ?? \"\"}\r\n          onValueChange={(v) => patch({ canonical: v || undefined })}\r\n          placeholder=\"https:\/\/example.com\/.well-known\/security.txt\"\r\n          data-x-input=\"security-canonical\"\r\n        \/>\r\n        <Input\r\n          label=\"Policy\"\r\n          value={value.policy ?? \"\"}\r\n          onValueChange={(v) => patch({ policy: v || undefined })}\r\n          placeholder=\"https:\/\/example.com\/security-policy\"\r\n          data-x-input=\"security-policy\"\r\n        \/>\r\n        <Input\r\n          label=\"Hiring\"\r\n          value={value.hiring ?? \"\"}\r\n          onValueChange={(v) => patch({ hiring: v || undefined })}\r\n          placeholder=\"https:\/\/example.com\/jobs\"\r\n          data-x-input=\"security-hiring\"\r\n        \/>\r\n      <\/Section>\r\n\r\n      {hideIssues ? null : <IssueList issues={issues} testid=\"securityTxt\" \/>}\r\n    <\/div>\r\n  );\r\n}\r\n","type":"registry:ui","target":"components\/fancy\/security-txt-editor\/SecurityTxtEditor.tsx"}]}