{
  "tag": "ed-file-input",
  "kind": "component",
  "summary": "File inputs let users pick one or more files from their device to submit with a form — no upload.",
  "status": "experimental",
  "level": "atom",
  "since": "1.0",
  "docs": "https://test-apps.eurodata.de/a/eurodata-ui/docs/components/file-input/",
  "usage": "https://test-apps.eurodata.de/a/eurodata-ui/docs/components/file-input/usage/",
  "playwright": "getByTestId('…')",
  "dependencies": [
    "ed-button",
    "ed-icon"
  ],
  "use": [
    "Attaching one or a few files to a form that is submitted as a whole — a supporting document, an attachment, a signed PDF",
    "Files that should travel with the surrounding form and be sent by the form's own submit, not uploaded the moment they are chosen",
    "Limiting an attachment to PDF files under a set size, with the limits stated beside the field"
  ],
  "notFor": [
    {
      "when": "Files that must be sent to the server immediately as they are chosen, with per-file progress and retry feedback",
      "instead": "[Upload](https://test-apps.eurodata.de/a/eurodata-ui/docs/components/upload)"
    },
    {
      "when": "A short typed value or a single choice",
      "instead": "[Input](https://test-apps.eurodata.de/a/eurodata-ui/docs/components/input)"
    }
  ],
  "rules": [
    {
      "id": "file-input/uploading-not-dropping",
      "rule": "Choose between File Input and [Upload](https://test-apps.eurodata.de/a/eurodata-ui/docs/components/upload) by whether the files are uploaded, never by drag-and-drop — both components offer it. File Input picks files; it does not upload them and shows no upload progress."
    },
    {
      "id": "file-input/accepted-types",
      "rule": "Declare the accepted file types, so the device's file dialog pre-filters and users pick the right file the first time.",
      "check": "error"
    },
    {
      "id": "file-input/limits",
      "rule": "Set a per-file size limit, a total-size limit and, when several files are allowed, a maximum count whenever real bounds exist.",
      "check": "warning"
    },
    {
      "id": "file-input/label-and-hint",
      "rule": "Give the field a clear label and a hint that states the accepted types and limits in plain language up front, such as \"PDF only, up to 5 MB each, 3 files max\".",
      "check": "error"
    },
    {
      "id": "file-input/built-in-file-rows",
      "rule": "Don't build your own review of the selection — the component shows each chosen file as a row with its name, size and a remove action, so users can review the selection before submitting.",
      "check": "warning"
    },
    {
      "id": "file-input/not-color-alone",
      "rule": "Never rely on a tinted border alone to signal an error or a warning — always pair the color with text."
    },
    {
      "id": "file-input/disabled-only-when-temporary",
      "rule": "Reserve the disabled state for cases where selection can become available under some condition — never for a field the user can never enable; present that as read-only context instead."
    },
    {
      "id": "form-controls/required",
      "rule": "Set `required` on a mandatory control and explain the required-marking convention once per form. Never add your own required indicator — the label picks it up."
    },
    {
      "id": "form-controls/error-timing",
      "rule": "Never show a validation error before the user has interacted with the control — not on page load, not on focus alone, not while they are still typing. Don't add your own timing: the control shows its errors after the user has left it or changed its value, and on submit.",
      "check": "error"
    },
    {
      "id": "form-controls/message-never-silenced",
      "rule": "Keep a message on every error. Write your own where the built-in wording does not fit — it replaces the built-in one — but never set `error` to an empty string or hide the message part: the error styling alone says that something is wrong, not what.",
      "check": "error"
    },
    {
      "id": "form-controls/min-width",
      "rule": "Keep a field at least 8.75rem (140px) wide, even for short values such as postal codes — and comfortably wider for prose.",
      "why": "The value, the label and any icons stay legible.",
      "check": "error",
      "covered": true
    }
  ],
  "api": {
    "attributes": [
      {
        "name": "multiple",
        "property": "multiple",
        "type": "boolean",
        "default": "false",
        "description": "Allow selecting/dropping more than one file. Mirrors the native input's `multiple`."
      },
      {
        "name": "accept",
        "property": "accept",
        "type": "string",
        "default": "''",
        "description": "Comma-separated list of accepted types (extensions and/or MIME types), like the native `accept`."
      },
      {
        "name": "max-files",
        "property": "maxFiles",
        "type": "null | number",
        "default": "null",
        "description": "Maximum number of files (multiple mode only)."
      },
      {
        "name": "max-file-size",
        "property": "maxFileSize",
        "type": "number",
        "default": "MAX_SIZE_MB",
        "description": "Maximum size per file in MB (capped at 2048)."
      },
      {
        "name": "max-total-file-size",
        "property": "maxTotalFileSize",
        "type": "number",
        "default": "MAX_SIZE_MB",
        "description": "Maximum total size of all selected files in MB (capped at 2048)."
      },
      {
        "name": "label",
        "property": "label",
        "type": "string",
        "default": "''",
        "description": "The file input's label. If you need to display HTML, use the `label` slot instead."
      },
      {
        "name": "aria-label",
        "property": "ariaLabel",
        "type": "null | string",
        "default": "null",
        "description": "The control's accessible name for when no visible label is set. Mirrored onto the internal\n`role=\"group\"` wrapper — an aria-label left on the host alone would sit on a role-less\nelement and be ignored by assistive tech — and carried by the trigger ahead of its action,\nas a visible label is."
      },
      {
        "name": "required",
        "property": "required",
        "type": "boolean",
        "default": "false",
        "description": "Makes the file input a required field: at least one file must be selected."
      },
      {
        "name": "with-label",
        "property": "withLabel",
        "type": "boolean",
        "default": "false",
        "description": "Only required for SSR. Set to `true` if you're slotting in a `label` element so the server-rendered markup\nincludes the label before the component hydrates on the client."
      },
      {
        "name": "error",
        "property": "error",
        "type": "null | string",
        "default": "null",
        "description": "Draws an error-style input with danger colored border and icon. Set to an empty string (or use the bare attribute `<ed-input error>`) to render error styling without a visible message; submission is still blocked with a localized fallback validation message. Set to a non-empty string to additionally display that message in the message area, above the hint, and use it as the validation message. Set to `null` (the default) or remove the attribute to clear the error."
      },
      {
        "name": "warning",
        "property": "warning",
        "type": "null | string",
        "default": "null",
        "description": "Draws a warning-style input with warning colored border and icon. Set to an empty string (or use the bare attribute `<ed-input warning>`) to render warning styling without a visible message. Set to a non-empty string to additionally display that message in the message area, above the hint. Warnings do not block form submission. Set to `null` (the default) or remove the attribute to clear the warning."
      },
      {
        "name": "ai",
        "property": "ai",
        "type": "boolean",
        "default": "false",
        "description": "Draws an ai-style input with AI colored border and icon. Suppressed visually once\n`hasInteracted` flips, but the property and attribute are preserved so the styling\nreturns after `formResetCallback` clears `hasInteracted`."
      },
      {
        "name": "hint",
        "property": "hint",
        "type": "string",
        "default": "''",
        "description": "The form control's hint text. If you need to display HTML, use the `hint` slot instead."
      },
      {
        "name": "name",
        "property": "name",
        "type": "null | string",
        "default": "null",
        "description": "The name of the input, submitted as a name/value pair with form data."
      },
      {
        "name": "disabled",
        "property": "disabled",
        "type": "boolean",
        "description": "Disables the form control. HTML treats a control as disabled when either its own `disabled` is\nset or an ancestor `<fieldset>` is disabled, so reading this reports the combined state while\nwriting it sets only this element's own. Keeping the two apart is what lets a fieldset be\nre-enabled without clearing a disabled state the consumer set in the meantime."
      },
      {
        "name": "dir",
        "property": "dir",
        "type": "string"
      },
      {
        "name": "lang",
        "property": "lang",
        "type": "string"
      }
    ],
    "properties": [
      {
        "name": "validationTarget",
        "type": "undefined | HTMLElement",
        "description": "Anchor validation state on the labelled group, not on the native input — that one is\n`aria-hidden`, so `aria-invalid` written there reaches nobody."
      },
      {
        "name": "value",
        "type": "File[]",
        "description": "The selected files, submitted as one `FormData` entry per file under `name`. An empty array means no\nselection. Setting this directly also repopulates the visible chip list (see `handleValueChange`), but does\nnot run `accept`/size validation — it is meant for restoring an already-known-good selection, not for\nfeeding it untrusted input.\n\nThe native \"restore form state\" flow (`formStateRestoreCallback`, browser back/forward cache or crash\nrecovery) cannot repopulate this: browsers never rehydrate `File` objects for `<input type=\"file\">` for\nsecurity reasons, and the same restriction applies here."
      },
      {
        "name": "files",
        "type": "File[]",
        "description": "The selected files. Convenience alias for `value`, matching `ed-upload`'s `files` getter."
      },
      {
        "name": "form",
        "type": "HTMLFormElement | null",
        "description": "By default, form controls are associated with the nearest containing `<form>` element. This attribute allows you\nto place the form control outside of a form and associate it with the form that has this `id`. The form must be in\nthe same document or shadow root for this to work."
      }
    ],
    "methods": [
      {
        "name": "focus",
        "parameters": [
          {
            "name": "options",
            "type": "FocusOptions",
            "optional": true
          }
        ],
        "description": "Focuses the trigger, the control the user operates — the host itself takes no focus."
      },
      {
        "name": "setCustomValidity",
        "parameters": [
          {
            "name": "message",
            "type": "string"
          }
        ],
        "description": "Do not use this when creating a \"Validator\". This is intended for end users of components.\nWe track manually defined custom errors so we don't clear them on accident in our validators."
      },
      {
        "name": "resetValidity",
        "description": "Reset validity is a way of removing manual custom errors and native validation."
      }
    ],
    "events": [
      {
        "name": "ed-file-input-change",
        "react": "onEdFileInputChange",
        "type": "{ files: File[] }",
        "description": "Emitted whenever the selection changes (a file is added or removed)."
      },
      {
        "name": "ed-invalid",
        "react": "onEdInvalid",
        "description": "Emitted when the form control has been checked for validity and its constraints aren't satisfied."
      }
    ],
    "slots": [
      {
        "name": "label",
        "description": "The file input's label. Alternatively, you can use the `label` attribute."
      },
      {
        "name": "hint",
        "description": "Text that describes how to use the file input. Alternatively, you can use the `hint` attribute."
      }
    ],
    "cssProperties": [],
    "parts": [
      {
        "name": "label",
        "description": "The label."
      },
      {
        "name": "form-control-label",
        "description": "Alias for the label element."
      },
      {
        "name": "message",
        "description": "The state message: an error, a warning, or the AI note."
      },
      {
        "name": "hint",
        "description": "The hint's wrapper."
      },
      {
        "name": "base",
        "description": "The component wrapper."
      },
      {
        "name": "dropzone",
        "description": "The drag & drop area."
      },
      {
        "name": "list",
        "description": "The file list."
      },
      {
        "name": "file",
        "description": "A single file row."
      },
      {
        "name": "file-name",
        "description": "A file row's name."
      },
      {
        "name": "file-size",
        "description": "A file row's size."
      },
      {
        "name": "file-actions",
        "description": "A file row's action buttons."
      },
      {
        "name": "file-reason",
        "description": "A rejected row's reason text."
      }
    ],
    "states": [
      {
        "name": "disabled",
        "description": "The control is disabled, by its own attribute or by an ancestor fieldset."
      },
      {
        "name": "required",
        "description": "The control is required."
      },
      {
        "name": "optional",
        "description": "The control is not required."
      },
      {
        "name": "invalid",
        "description": "The value fails constraint validation, whether or not the user has touched the control yet."
      },
      {
        "name": "valid",
        "description": "The value passes constraint validation."
      },
      {
        "name": "user-invalid",
        "description": "Invalid, and the user has interacted with the control. This is the one to style for an error: it behaves like the platform's `:user-invalid`, so an untouched field is not marked wrong before the user has had a chance to fill it in."
      },
      {
        "name": "user-valid",
        "description": "Valid, and the user has interacted with the control."
      },
      {
        "name": "dirty",
        "description": "The user has interacted with the control."
      },
      {
        "name": "error",
        "description": "The `error` property is set, or the control is `user-invalid`."
      },
      {
        "name": "warning",
        "description": "The `warning` property is set."
      },
      {
        "name": "ai",
        "description": "The `ai` property is set and the user has not interacted with the control yet."
      }
    ]
  },
  "import": "import '@eurodata/eurodata-ui/dist/components/file-input/file-input.js';",
  "react": {
    "component": "EdFileInput",
    "import": "import EdFileInput from '@eurodata/eurodata-ui/dist/react/file-input/index.js';"
  }
}
