{
  "tag": "ed-number-input",
  "kind": "component",
  "summary": "Number inputs allow users to enter and edit numeric values with stepper buttons.",
  "status": "experimental",
  "since": "1.0",
  "docs": "https://test-apps.eurodata.de/a/eurodata-ui/docs/components/number-input/",
  "usage": "https://test-apps.eurodata.de/a/eurodata-ui/docs/components/number-input/usage/",
  "playwright": "getByTestId('…').getByRole('spinbutton')",
  "dependencies": [
    "ed-icon"
  ],
  "use": [
    "A countable, steppable value with a clear default that users typically nudge up or down by a step or two — number of guests, copies, line items",
    "A value that must obey a fixed granularity — the steppers move on the grid of allowed values, and a value typed off-grid is reported as invalid rather than silently corrected",
    "A quantity or number of items that the user raises or lowers with the arrow buttons",
    "A small integer field such as the number of months or installments, with a minimum and maximum checked by the field"
  ],
  "notFor": [
    {
      "when": "Wide-variability values (age, a year such as the birth year, salary), prices, open-ended amounts, or large ranges — reaching the target takes too many clicks",
      "instead": "[Input](https://test-apps.eurodata.de/a/eurodata-ui/docs/components/input) with the number type (unit icon in the end slot, spin buttons hidden)"
    },
    {
      "when": "Numbers that are really formatted identifiers — phone numbers, IBANs, postal codes, card numbers, order references",
      "instead": "a text [Input](https://test-apps.eurodata.de/a/eurodata-ui/docs/components/input)"
    },
    {
      "when": "Picking from a short list of preset amounts",
      "instead": "a [Select](https://test-apps.eurodata.de/a/eurodata-ui/docs/components/select) or [Radio Group](https://test-apps.eurodata.de/a/eurodata-ui/docs/components/radio-group)"
    },
    {
      "when": "Decimal numbers",
      "instead": "an [Input](https://test-apps.eurodata.de/a/eurodata-ui/docs/components/input) of type number"
    }
  ],
  "rules": [
    {
      "id": "number-input/stepping-helps",
      "rule": "Reach for Number Input only when stepping genuinely helps — values that stay in a small range around a common default (roughly 1–100), like a quantity of items.",
      "why": "The steppers are this component's reason to exist."
    },
    {
      "id": "number-input/visible-label",
      "rule": "Give every field in a form a persistent, visible label — never placeholder text as its only label. Outside a form, where the surroundings say what it is, an `aria-label` may take its place.",
      "check": "error"
    },
    {
      "id": "number-input/hint-states-constraints",
      "rule": "State the unit, the allowed range and the step size in the hint (for example \"Amount in euros, 10–100, in steps of 5\").",
      "check": "warning"
    },
    {
      "id": "number-input/min-width",
      "rule": "Keep the field at least 8.75rem (140px) wide, even for short values.",
      "why": "The value, the label and any icons stay legible.",
      "check": "error"
    },
    {
      "id": "number-input/value-prominence",
      "rule": "Let the value be visually more prominent than its label when the two are shown together."
    },
    {
      "id": "number-input/error-timing",
      "rule": "Don't add your own timing for validation errors — the component shows them only after the user has typed and left the field, or on submit. Never show an error state on page load or the moment the field is focused, before the user has entered anything.",
      "check": "error"
    },
    {
      "id": "number-input/specific-errors",
      "rule": "Write a specific, actionable message for each custom validation error — never a vague one like \"Invalid input\" or \"Error\". Don't write your own for the standard constraints (required, range, step) — the component has their messages.",
      "check": "error"
    },
    {
      "id": "number-input/required",
      "rule": "Set `required` on mandatory fields and explain the required-marking convention once per form. Don't add your own required indicator — the label picks it up automatically."
    },
    {
      "id": "number-input/readonly-not-disabled",
      "rule": "Use read-only for a value the user can never change (calculated totals, assigned IDs), and disabled only when it could become editable under some condition.",
      "why": "Disabled implies the value could be unlocked."
    },
    {
      "id": "number-input/ai-suggested",
      "rule": "Use the AI-suggested state to flag a value the system pre-filled, so users can tell it apart from their own entries."
    },
    {
      "id": "number-input/default-density",
      "rule": "Keep `density` at its default, and the same for every control in one row or form. Choose `compact` for a control in a [Data Grid](https://test-apps.eurodata.de/a/eurodata-ui/docs/components/data-grid) cell — never in the grid's toolbar, which keeps the default of the grid's own search. Elsewhere choose `compact` or `spacious` only deliberately, for a whole layout that is tighter or looser — never to fine-tune spacing case by case.",
      "why": "The default suits standard forms and layouts, and it is the intended spacing for almost every screen.",
      "check": "warning"
    }
  ],
  "api": {
    "attributes": [
      {
        "name": "title",
        "property": "title",
        "type": "string",
        "default": "''"
      },
      {
        "name": "value",
        "property": "defaultValue",
        "type": "string",
        "description": "The default value of the form control. Primarily used for resetting the form control."
      },
      {
        "name": "density",
        "property": "density",
        "type": "'compact' | 'default' | 'spacious'",
        "default": "'default'",
        "description": "Controls the component's spacing density without affecting font-size."
      },
      {
        "name": "pill",
        "property": "pill",
        "type": "boolean",
        "default": "false",
        "description": "Draws a pill-style input with rounded edges."
      },
      {
        "name": "label",
        "property": "label",
        "type": "string",
        "default": "''",
        "description": "The 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 input's accessible name for when no visible label is set. Mirrored onto the internal\ninput, where the spinbutton role lives — an aria-label left on the host alone would sit on\na role-less element and be ignored by assistive tech."
      },
      {
        "name": "placeholder",
        "property": "placeholder",
        "type": "string",
        "default": "''",
        "description": "Placeholder text to show as a hint when the input is empty."
      },
      {
        "name": "readonly",
        "property": "readonly",
        "type": "boolean",
        "default": "false",
        "description": "Makes the input readonly."
      },
      {
        "name": "required",
        "property": "required",
        "type": "boolean",
        "default": "false",
        "description": "Makes the input a required field."
      },
      {
        "name": "min",
        "property": "min",
        "type": "number",
        "description": "The input's minimum value."
      },
      {
        "name": "max",
        "property": "max",
        "type": "number",
        "description": "The input's maximum value."
      },
      {
        "name": "step",
        "property": "step",
        "type": "number",
        "description": "The granularity the value must adhere to. Anything that cannot form a grid — `any`, zero,\nnegative, unparseable — falls back to `1`.\n\nA native input also takes `any`, which turns stepping off entirely. This control does not,\nbecause a numeric field without steps is `<ed-input type=\"number\">`: stepper buttons are the\nreason to reach for this element, and `stepUp()` throws `InvalidStateError` in a mode that has\nno step — so the buttons would be there and broken."
      },
      {
        "name": "without-steppers",
        "property": "withoutSteppers",
        "type": "boolean",
        "default": "false",
        "description": "Hides the increment/decrement stepper buttons."
      },
      {
        "name": "autocomplete",
        "property": "autocomplete",
        "type": "string",
        "description": "Specifies what permission the browser has to provide assistance in filling out form field values. Refer to\n[this page on MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/autocomplete) for available values."
      },
      {
        "name": "autofocus",
        "property": "autofocus",
        "type": "boolean",
        "description": "Indicates that the input should receive focus on page load."
      },
      {
        "name": "enterkeyhint",
        "property": "enterkeyhint",
        "type": "'next' | 'previous' | 'search' | 'send' | 'done' | 'enter' | 'go'",
        "description": "Used to customize the label or icon of the Enter key on virtual keyboards."
      },
      {
        "name": "inputmode",
        "property": "inputmode",
        "type": "'numeric' | 'decimal'",
        "default": "'numeric'",
        "description": "Tells the browser what type of data will be entered by the user, allowing it to display the appropriate virtual\nkeyboard on supportive devices."
      },
      {
        "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 includes the label before the component hydrates on the client."
      },
      {
        "name": "with-hint",
        "property": "withHint",
        "type": "boolean",
        "default": "false",
        "description": "Only required for SSR. Set to `true` if you're slotting in a `hint` element so the server-rendered markup includes the hint 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": "value",
        "type": "string",
        "description": "The current value of the input, submitted as a name/value pair with form data. Empty is `''`,\nas on a native number input — never `null`."
      },
      {
        "name": "valueAsNumber",
        "type": "number",
        "description": "The current value as a number, and `NaN` while the control holds no usable one. An empty field\nand a field whose text is not a number give the same answer, because value has already\nemptied the second one.\n\nWriting `NaN` empties the control, and writing an infinity throws a `TypeError` — both as HTML\nrequires of the native setter. Neither `min`, `max` nor `step` corrects what is written: an\nout-of-range number is kept and reported through `validity.rangeOverflow`, as on a native input."
      },
      {
        "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."
      },
      {
        "name": "validationTarget",
        "type": "undefined | HTMLElement",
        "description": "Override this to change where constraint validation popups are anchored."
      }
    ],
    "methods": [
      {
        "name": "focus",
        "parameters": [
          {
            "name": "options",
            "type": "FocusOptions",
            "optional": true
          }
        ],
        "description": "Sets focus on the input."
      },
      {
        "name": "blur",
        "description": "Removes focus from the input."
      },
      {
        "name": "select",
        "description": "Selects all the text in the input."
      },
      {
        "name": "stepUp",
        "description": "Increments the value by the step amount."
      },
      {
        "name": "stepDown",
        "description": "Decrements the value by the step amount."
      },
      {
        "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": "input",
        "react": "onInput",
        "type": "InputEvent",
        "description": "Emitted when the control receives input."
      },
      {
        "name": "change",
        "react": "onChange",
        "type": "Event",
        "description": "Emitted when an alteration to the control's value is committed by the user."
      },
      {
        "name": "blur",
        "react": "onBlur",
        "description": "Emitted when the control loses focus."
      },
      {
        "name": "beforeinput",
        "react": "onBeforeinput",
        "description": "Emitted from a stepper button before the value changes. Call `event.preventDefault()` to cancel the change."
      },
      {
        "name": "focus",
        "react": "onFocus",
        "description": "Emitted when the control gains focus."
      },
      {
        "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 input's label. Alternatively, you can use the `label` attribute."
      },
      {
        "name": "start",
        "description": "An element, such as `<ed-icon>`, placed at the start of the input control."
      },
      {
        "name": "end",
        "description": "An element, such as `<ed-icon>`, placed at the end of the input control (before steppers)."
      },
      {
        "name": "increment-icon",
        "description": "An icon to use in lieu of the default increment icon."
      },
      {
        "name": "decrement-icon",
        "description": "An icon to use in lieu of the default decrement icon."
      },
      {
        "name": "hint",
        "description": "Text that describes how to use the input. Alternatively, you can use the `hint` attribute."
      }
    ],
    "cssProperties": [
      {
        "name": "--ed-number-input-width",
        "description": "Sets a fixed width for the input field"
      }
    ],
    "parts": [
      {
        "name": "label",
        "description": "The label element."
      },
      {
        "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 element."
      },
      {
        "name": "base",
        "description": "The wrapper containing the input and steppers."
      },
      {
        "name": "input",
        "description": "The internal `<input>` control."
      },
      {
        "name": "start",
        "description": "The container that wraps the `start` slot."
      },
      {
        "name": "end",
        "description": "The container that wraps the `end` slot."
      },
      {
        "name": "stepper",
        "description": "Both stepper buttons (for shared styling)."
      },
      {
        "name": "stepper-increment",
        "description": "The increment (+) button on the end side."
      },
      {
        "name": "stepper-decrement",
        "description": "The decrement (-) button on the start side."
      }
    ],
    "states": [
      {
        "name": "blank",
        "description": "The input is empty."
      },
      {
        "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/number-input/number-input.js';",
  "react": {
    "component": "EdNumberInput",
    "import": "import EdNumberInput from '@eurodata/eurodata-ui/dist/react/number-input/index.js';"
  }
}
