{
  "version": "0.2.0-preview.1",
  "content_digest": "70ac710f4d22dce040e7ac593379ba8aca9dcb59a0b9c0f839819cae0e2bb721",
  "status": "preview",
  "authority": {
    "repository": "cloakedinc/design",
    "path": "packages/design-system",
    "catalog": "packages/design-system/catalog.json",
    "status": "preview"
  },
  "provenance": {
    "repo": "cloakedinc/automation",
    "commit": "f96f416e1c3bfbfaffcd155a88b87b18b8bb25f1",
    "path": "packages/design-system",
    "imported_spec_status": "approved"
  },
  "adaptations": [
    {
      "id": "button-content-gap",
      "status": "preview",
      "description": "Use the specification's 4px content gap instead of the inherited 8px implementation gap."
    },
    {
      "id": "keyboard-focus",
      "status": "preview",
      "description": "Add visible Button and Input keyboard focus and an overridable inset focus default for shared button resets, including FAQ cards and ListItem rows."
    },
    {
      "id": "supporting-text-contrast",
      "status": "preview",
      "description": "Map light secondary text to the existing grey-04-strong primitive for readable helper text on white and cream."
    },
    {
      "id": "danger-text-contrast",
      "status": "preview",
      "description": "Separate readable danger text/borders from destructive fills; preserve the primary danger-button fill and label pair."
    },
    {
      "id": "preview-status",
      "status": "preview",
      "description": "Local components, specs and token adaptations await human sign-off; upstream approved status is provenance only."
    },
    {
      "id": "motion-comparison-accessibility",
      "status": "preview",
      "description": "Preserve the original MotionShowcase comparisons while requiring explicit replay, responding to live reduced-motion changes, and keeping duration tracks usable on small screens."
    },
    {
      "id": "list-item-ownership",
      "status": "preview",
      "description": "List owns listitem wrappers for its content rows, while section labels stay outside the row count and standalone rows retain their existing semantics."
    },
    {
      "id": "card-delta-text-contrast",
      "status": "preview",
      "description": "Mix Card.Delta foregrounds from 60% existing tone solid and 40% primary text for readable contrast in both themes; preserve the four original tone fills."
    },
    {
      "id": "carousel-keyboard-access",
      "status": "preview",
      "description": "Keep all native-scrolling carousel slide controls exposed to assistive technology and keyboard navigation; pause autoplay while focus is inside the carousel."
    }
  ],
  "id": "input",
  "name": "Input",
  "category": "Primitives",
  "summary": "A controlled text input, paired with Field for a persistent label and useful validation.",
  "documentation": {
    "summary": "A controlled text input, paired with Field for a persistent label and useful validation.",
    "when_to_use": [
      "Collect a single-line value.",
      "Choose the native input type for the value being collected.",
      "Place one Input inside each Field."
    ],
    "avoid": [
      "Using placeholder text as the only label.",
      "Rendering a controlled input without onChange unless readOnly or disabled.",
      "Showing a red ring without explanatory text."
    ],
    "accessibility": [
      "Field connects the visible label and helper or error text to the input.",
      "Use autoComplete and inputMode when applicable.",
      "Keyboard focus surrounds the complete control."
    ],
    "constraints": [
      "value is required; onChange receives the edited string.",
      "Use surface=raised directly on a page canvas.",
      "The return key advances within a form or data-cds-form-scope unless callback behavior is selected."
    ]
  },
  "source": {
    "path": "packages/design-system/src/components/primitives/Input/Input.tsx",
    "code": "import React from 'react';\nimport { cn } from '../../../utilities';\nimport { useFieldControl, type FieldControlProps } from '../../../hooks/FieldContext';\nimport { useInputReturnKey } from './useInputReturnKey';\nimport styles from './Input.module.scss';\n\nexport type InputType = 'text' | 'password' | 'email' | 'tel' | 'url' | 'search' | 'number' | 'date';\nexport type InputSize = 'sm' | 'md';\nexport type InputEnterBehavior = 'advance' | 'callback';\nexport type InputEnterKeyHint = 'enter' | 'done' | 'go' | 'next' | 'previous' | 'search' | 'send';\n\nconst DEFAULT_PLACEHOLDERS: Partial<Record<InputType, string>> = {\n    email: 'Email',\n    password: 'Password',\n    tel: 'Phone number',\n    url: 'Website',\n    search: 'Search',\n    number: 'Number',\n};\n\n/**\n * Container background treatment.\n *\n * `default` is the cream field used on white surfaces. `raised` switches the\n * container to the elevated surface color so the field reads correctly when it\n * sits directly on a cream page canvas (e.g. inside a cream sheet/modal).\n */\nexport type InputSurface = 'default' | 'raised';\n\n/**\n * Props for the single-line text field. Controlled only: `value` is required, and omitting\n * `onChange` freezes the field without the disabled or read-only styling that would explain it.\n */\nexport interface InputProps extends FieldControlProps {\n    /** Current field value (controlled). */\n    value: string;\n    /** Called with the next value on each edit. */\n    onChange?: (value: string) => void;\n    /** Called when Enter is pressed while focused. */\n    onEnter?: () => void;\n    /**\n     * Return-key behavior. `advance` moves focus to the next compatible form\n     * control before falling back to `onEnter`.\n     */\n    enterBehavior?: InputEnterBehavior;\n    /** Native on-screen keyboard return key hint. */\n    enterKeyHint?: InputEnterKeyHint;\n    /** Placeholder text. Falls back to a wording keyed off `type`; `text` and `date` have none. */\n    placeholder?: string;\n    /** Field size. Defaults to `md` for backwards-compatible form density. */\n    size?: InputSize;\n    /**\n     * Native input type, which also picks the default placeholder. `search` additionally defaults\n     * `enterBehavior` to `callback`, so its return key submits instead of moving focus.\n     */\n    type?: InputType;\n    /** Container background treatment; use `raised` on cream canvases. */\n    surface?: InputSurface;\n    /** Blocks editing and focus, and dims the field. Prefer `readOnly` to keep it focusable. */\n    disabled?: boolean;\n    /** Accessible name when no visible label is associated with the field. */\n    ariaLabel?: string;\n    /** ID of an associated popup/list controlled by this input. */\n    ariaControls?: string;\n    /** On-screen keyboard hint (e.g. `numeric` for SSN/phone fields). */\n    inputMode?: React.InputHTMLAttributes<HTMLInputElement>['inputMode'];\n    /** Native character-count limit on typed input. */\n    maxLength?: number;\n    /** Native autocomplete hint. */\n    autoComplete?: string;\n    /** Native autocorrect hint. */\n    autoCorrect?: 'on' | 'off';\n    /** Native autocapitalize hint. */\n    autoCapitalize?: 'off' | 'none' | 'on' | 'sentences' | 'words' | 'characters';\n    /** Native spellcheck hint. */\n    spellCheck?: boolean;\n    /** Form field name. */\n    name?: string;\n    /** Prevents editing while preserving focus and form submission semantics. */\n    readOnly?: boolean;\n    /** Native minimum value constraint. */\n    min?: React.InputHTMLAttributes<HTMLInputElement>['min'];\n    /** Native maximum value constraint. */\n    max?: React.InputHTMLAttributes<HTMLInputElement>['max'];\n    /** Native numeric step constraint. */\n    step?: React.InputHTMLAttributes<HTMLInputElement>['step'];\n    /** Native validation pattern. */\n    pattern?: string;\n    /** Optional leading content inside the field shell. */\n    leading?: React.ReactNode;\n    /** Optional trailing content inside the field shell. */\n    trailing?: React.ReactNode;\n    /** Optional trailing action inside the field shell. */\n    trailingAction?: React.ReactNode;\n    /** Called when the field gains focus. */\n    onFocus?: () => void;\n    /** Called on blur, before any return-key advance moves focus on to the next control. */\n    onBlur?: () => void;\n    /** Class hook for the field wrapper. */\n    className?: string;\n    /** Inline style override for the field wrapper. */\n    style?: React.CSSProperties;\n    /** Optional test selector. Lands on the `<input>`. */\n    testId?: string;\n}\n\n/**\n * The single-line text field. It renders no label or message of its own — wrap it in `Field` for\n * those, and the Field's `error` drives the invalid treatment here through context. For the return\n * key to advance between fields, put them inside a `<form>` or a `[data-cds-form-scope]` element.\n */\nexport function Input({\n    value,\n    onChange,\n    onEnter,\n    enterBehavior,\n    enterKeyHint,\n    placeholder,\n    size = 'md',\n    type = 'text',\n    surface = 'default',\n    invalid,\n    disabled,\n    required,\n    ariaLabel,\n    ariaDescribedBy,\n    ariaLabelledBy,\n    ariaControls,\n    inputMode,\n    maxLength,\n    autoComplete,\n    autoCorrect,\n    autoCapitalize,\n    spellCheck,\n    name,\n    readOnly,\n    min,\n    max,\n    step,\n    pattern,\n    leading,\n    trailing,\n    trailingAction,\n    id,\n    onFocus,\n    onBlur,\n    className,\n    style,\n    testId,\n}: InputProps) {\n    const field = useFieldControl({ id, disabled, required, invalid, ariaDescribedBy, ariaLabelledBy });\n    const hasSlots = Boolean(leading || trailing || trailingAction);\n    const resolvedEnterBehavior = enterBehavior ?? (onEnter || type === 'search' ? 'callback' : 'advance');\n    const { handleKeyDown, handleBeforeInput, handleInput, handleFocus, handleBlur } = useInputReturnKey({\n        resolvedEnterBehavior,\n        enterKeyHint,\n        onEnter,\n        onFocus,\n        onBlur,\n    });\n\n    return (\n        <div className={cn(styles.root, className)} style={style}>\n            <div\n                className={cn(\n                    styles.control,\n                    styles[`size-${size}`],\n                    styles[`surface-${surface}`],\n                    field.disabled && styles.controlDisabled,\n                    hasSlots && styles.withSlots\n                )}\n                data-invalid={field.invalid || undefined}\n            >\n                {leading && <span className={styles.leading}>{leading}</span>}\n                <input\n                    type={type}\n                    className={styles.field}\n                    value={value}\n                    onChange={event => onChange?.(event.target.value)}\n                    onKeyDown={handleKeyDown}\n                    onBeforeInput={handleBeforeInput}\n                    onInput={handleInput}\n                    placeholder={placeholder ?? DEFAULT_PLACEHOLDERS[type]}\n                    disabled={field.disabled}\n                    required={field.required}\n                    inputMode={inputMode}\n                    enterKeyHint={enterKeyHint}\n                    maxLength={maxLength}\n                    autoComplete={autoComplete}\n                    autoCorrect={autoCorrect}\n                    autoCapitalize={autoCapitalize}\n                    spellCheck={spellCheck}\n                    name={name}\n                    readOnly={readOnly}\n                    min={min}\n                    max={max}\n                    step={step}\n                    pattern={pattern}\n                    id={field.id}\n                    onFocus={handleFocus}\n                    onBlur={handleBlur}\n                    aria-label={ariaLabel}\n                    aria-labelledby={field.ariaLabelledBy}\n                    aria-invalid={field.invalid || undefined}\n                    aria-describedby={field.ariaDescribedBy}\n                    aria-controls={ariaControls}\n                    data-testid={testId}\n                />\n                {trailing && <span className={styles.trailing}>{trailing}</span>}\n                {trailingAction && <span className={styles.trailingAction}>{trailingAction}</span>}\n            </div>\n        </div>\n    );\n}\n"
  },
  "spec": {
    "$schema": "../../../specs/component-spec.schema.json",
    "identity": {
      "name": "Input",
      "status": "preview",
      "version": "2.0.0",
      "summary": "A controlled single-line text field with native keyboard types, compact and standard sizes, slots, invalid state, and mobile return-key behavior. It renders no label or message of its own."
    },
    "parts": [
      {
        "id": "wrapper",
        "label": "Wrapper",
        "description": "Carries the caller's class and style around the control."
      },
      {
        "id": "control",
        "label": "Control",
        "description": "Owns the pill surface, selected size, invalid ring, and optional slots."
      },
      {
        "id": "field",
        "label": "Field",
        "description": "Provides native single-line input, keyboard, validation, and form semantics."
      },
      {
        "id": "leading",
        "label": "Leading slot",
        "description": "Holds a non-expanding icon or prefix before the field."
      },
      {
        "id": "trailing",
        "label": "Trailing slot",
        "description": "Holds a non-expanding suffix after the field."
      },
      {
        "id": "trailing-action",
        "label": "Trailing action",
        "description": "Holds a compact interactive action such as clear or show password."
      }
    ],
    "allowedDesignChoices": {
      "variants": {
        "base": {
          "label": "Base",
          "description": "The field has one pill-shaped control treatment."
        }
      },
      "sizes": {
        "sm": {
          "label": "Small"
        },
        "md": {
          "label": "Medium"
        }
      },
      "types": {
        "text": {
          "label": "Text",
          "description": "General single-line content with no more specific native input type."
        },
        "password": {
          "label": "Password",
          "description": "Masks a secret value and requests password input behavior."
        },
        "email": {
          "label": "Email",
          "description": "Requests an email keyboard and native email validation."
        },
        "tel": {
          "label": "Telephone",
          "description": "Requests a telephone keyboard for phone values."
        },
        "url": {
          "label": "URL",
          "description": "Requests a URL keyboard and native URL validation."
        },
        "search": {
          "label": "Search",
          "description": "Provides native search semantics for a bare search field."
        },
        "number": {
          "label": "Number",
          "description": "Supports native numeric minimum, maximum, and step constraints."
        },
        "date": {
          "label": "Date",
          "description": "Requests the native date picker; the value is an ISO YYYY-MM-DD string and the placeholder is platform-owned."
        }
      },
      "surfaces": {
        "default": {
          "label": "Default",
          "description": "Uses the input-container role on a raised host surface."
        },
        "raised": {
          "label": "Raised",
          "description": "Uses the raised surface role when the field sits directly on the page canvas."
        }
      }
    },
    "variants": [
      {
        "id": "base",
        "label": "Base",
        "description": "One pill-shaped field treatment configured through the separate type, surface, and size axes.",
        "platforms": [
          "ios",
          "android",
          "web"
        ]
      }
    ],
    "sizes": [
      {
        "id": "sm",
        "label": "Small",
        "description": "40-unit compact field for dense contexts."
      },
      {
        "id": "md",
        "label": "Medium",
        "description": "56-unit standard form field."
      }
    ],
    "measurements": [
      {
        "id": "small-height",
        "label": "Small control height",
        "kind": "exact",
        "token": "--cds-size-40",
        "value": 40,
        "unit": "px",
        "appliesTo": [
          "control",
          "sm"
        ]
      },
      {
        "id": "medium-height",
        "label": "Medium control height",
        "kind": "exact",
        "token": "--cds-size-56",
        "value": 56,
        "unit": "px",
        "appliesTo": [
          "control",
          "md"
        ]
      },
      {
        "id": "slot-gap",
        "label": "Slot gap",
        "kind": "exact",
        "token": "--cds-space-8",
        "value": 8,
        "unit": "px",
        "appliesTo": [
          "leading",
          "field",
          "trailing",
          "trailing-action"
        ]
      }
    ],
    "layout": {
      "alignment": "Field text and slots align on the control center line.",
      "flow": "Leading slot, flexible field, trailing slot, and trailing action form one row.",
      "notes": [
        "Wrap Input in Field for a visible label, helper text, or any validation copy; Field is the only owner of error messages.",
        "The control fills its parent width."
      ]
    },
    "typographyAndColor": {
      "typography": [
        {
          "label": "Medium field text",
          "description": "Standard fields use the body ramp.",
          "token": "--cds-type-body-size"
        },
        {
          "label": "Small field text",
          "description": "Compact fields use the body-small ramp outside the web anti-zoom floor.",
          "token": "--cds-type-body-small-size"
        }
      ],
      "colors": [
        {
          "label": "Default container",
          "description": "Uses the theme-aware input surface.",
          "token": "--cds-input-container"
        },
        {
          "label": "Raised container",
          "description": "Uses the raised surface role on a page canvas.",
          "token": "--cds-bg-surface"
        },
        {
          "label": "Field text",
          "description": "Uses primary text emphasis.",
          "token": "--cds-text-primary"
        },
        {
          "label": "Placeholder and slots",
          "description": "Use secondary text emphasis.",
          "token": "--cds-text-secondary"
        },
        {
          "label": "Invalid",
          "description": "Use the readable semantic danger role for error indication in both themes.",
          "token": "--cds-text-danger"
        }
      ]
    },
    "states": [
      {
        "id": "empty",
        "label": "Empty",
        "description": "Shows the explicit or type-specific placeholder."
      },
      {
        "id": "focused",
        "label": "Focused",
        "description": "Accepts input and shows a caret; there is no focus ring, since the design system targets a touch surface and the keyboard/caret already signal focus."
      },
      {
        "id": "filled",
        "label": "Filled",
        "description": "Shows the controlled value in primary text."
      },
      {
        "id": "invalid",
        "label": "Invalid",
        "description": "Shows the danger ring and invalid semantics; the control renders no message of its own. An enclosing Field supplies the corrective copy, and a standalone caller renders it elsewhere, such as a form-level summary."
      },
      {
        "id": "disabled",
        "label": "Disabled",
        "description": "Blocks editing and dims the whole control."
      },
      {
        "id": "read-only",
        "label": "Read only",
        "description": "Preserves focus and form semantics while preventing edits."
      }
    ],
    "behavior": [
      {
        "label": "Controlled editing",
        "description": "Request the next string on every edit while the parent owns the rendered value."
      },
      {
        "label": "Return-key behavior",
        "description": "Support advance to the next compatible field or invoke a callback; search and explicit callbacks default to callback behavior."
      },
      {
        "label": "Return-key labels",
        "description": "Support enter, done, go, next, previous, search, and send keyboard hints."
      },
      {
        "label": "Native types",
        "description": "Preserve text, password, email, telephone, URL, search, number, and date input semantics."
      }
    ],
    "accessibility": [
      {
        "label": "Accessible name",
        "description": "Associate a visible Field label or provide an accessible label when the input stands alone."
      },
      {
        "label": "Error relationship",
        "description": "Report invalid state on the control itself and render no message. An enclosing Field associates its rendered message with the control; a standalone caller associates the copy it renders elsewhere."
      },
      {
        "label": "Trailing actions",
        "description": "Give every interactive trailing action its own accessible name and stable test identifier."
      }
    ],
    "contentAdaptation": [
      {
        "label": "Placeholders",
        "description": "Use placeholders as examples or hints, never as the only persistent visible label for complex forms."
      },
      {
        "label": "Long values",
        "description": "Let the native single-line field scroll horizontally; use Textarea for multiline content."
      }
    ],
    "motionHaptics": {
      "motion": [
        {
          "label": "Focus and validation",
          "description": "Change borders and rings without moving the control."
        }
      ],
      "haptics": [
        {
          "label": "No intrinsic feedback",
          "description": "Typing and focus do not request design-system haptics; a trailing action owns its own feedback."
        }
      ]
    },
    "platformDifferences": [
      {
        "platforms": [
          "web"
        ],
        "description": "Small field text is floored at the 16px body size in the webview instead of rendering the 14px body-small size.",
        "rationale": "WKWebView zooms focused inputs below 16px; the font floor prevents an unexpected viewport jump while retaining the compact 40px shell."
      }
    ]
  },
  "spec_source": "packages/design-system/src/components/primitives/Input/Input.spec.json",
  "guidance_source": {
    "path": "packages/design-system/src/components/primitives/Input/Input.mdx",
    "code": "import { Meta, Canvas, Controls } from '@storybook/addon-docs/blocks';\nimport { ComponentSpec, UsageTable } from '../../../../.storybook/blocks';\nimport * as Stories from './Input.stories';\nimport inputSpec from './Input.spec.json';\n\n<Meta of={Stories} />\n\n# Input\n\nThe text box and nothing else. It renders no label, no helper text, and no error\nmessage — wrap it in `Field` for those. Use `Textarea` for multi-line and\n`SearchField` for the full search chrome.\n\n<Canvas of={Stories.Playground} />\n\n## Use when\n\nPick `type` for the value the field holds. It drives the native keyboard and\nvalidation, not just the mask.\n\n<UsageTable\n    axis='Type'\n    rows={[\n        {\n            variant: 'text',\n            use: 'Free-form single-line text with no better-fitting type — names, cities, labels. The default.',\n            avoid: 'A value a more specific type validates better (email, tel, url, number).',\n        },\n        {\n            variant: 'email',\n            use: 'An email address — opens the email keyboard and validates the value.',\n        },\n        {\n            variant: 'password',\n            use: 'A secret value that should be masked. Pair with a show/hide toggle in trailingAction.',\n        },\n        {\n            variant: 'tel',\n            use: 'A phone number — opens the phone keypad. Set inputMode=\"numeric\" for digit-only fields like SSN.',\n        },\n        {\n            variant: 'url',\n            use: 'A web address — opens the URL keyboard.',\n        },\n        {\n            variant: 'search',\n            use: 'A search query. Prefer SearchField for the full search chrome; reach here only for a bare search input.',\n        },\n        {\n            variant: 'number',\n            use: 'A numeric value with min / max / step constraints.',\n        },\n    ]}\n/>\n\n`text`, `email`, `tel`, and `password` cover today's form fields. `url`, `search`,\nand `number` work but nothing in the app uses them yet.\n\n<Canvas of={Stories.Types} />\n\n## Surface\n\n**The default field fill is the same cream as the page canvas** — both resolve to\n`--cds-color-grey-01` in the light theme — so a `default` field placed directly on\na page disappears. That is why these stories paint their canvas white: it is where\na form actually sits, inside a card or a sheet.\n\nWhen the field really does sit on the cream canvas, switch to `raised`.\n\n<Canvas of={Stories.RaisedOnCanvas} />\n\n## Size and content\n\n`md` (56px) is the default and what app forms use. `sm` (40px) is for a compact row\nsuch as an inline search. Reach for it only where vertical space is tight.\n\n`leading`, `trailing`, and `trailingAction` place icons, units, and compact actions\ninside the field shell. Below, an `md` field using all three slots, then an `sm`\nsearch field.\n\n<Canvas of={Stories.WithSlots} />\n\n## States\n\n`Field` owns validation copy. Setting `error` on the Field renders the message and\nturns the Input red through context — you set the error once. An Input that passes\nits own `invalid` keeps it, so `invalid={false}` opts out of the Field's ring.\n\n<Canvas of={Stories.InvalidInField} />\n\n`invalid` on the Input is the escape hatch for a control with no `Field` around it,\nsuch as a field whose only error text lives in a summary at the top of the form. It\npaints the ring and sets `aria-invalid`; it renders no text. A red ring with no\nmessage anywhere fails WCAG 1.4.1, so pair it with copy the user can read.\n\nEvery resting state, including that escape hatch and `disabled`:\n\n<Canvas of={Stories.StateMatrix} />\n\nFocus is a separate axis — the caret and active placeholder appear on top of\nwhichever resting state the field is in:\n\n<Canvas of={Stories.Focused} />\n\n## Accessibility\n\nInside a `Field`, the label, message, and `aria-describedby` wiring are handled for\nyou. Standalone, pass `ariaLabel` so the control has an accessible name.\n\n## Dark theme\n\n<Canvas of={Stories.DarkTheme} />\n\n## Design Guidelines\n\n<ComponentSpec spec={inputSpec} />\n\n## Props\n\n<Controls of={Stories.Playground} />\n"
  },
  "props": [
    {
      "name": "id",
      "type": "string",
      "required": false,
      "description": "DOM id the control renders, which the Field's label points at."
    },
    {
      "name": "disabled",
      "type": "boolean",
      "required": false,
      "description": "Blocks editing and focus, and dims the field. Prefer `readOnly` to keep it focusable."
    },
    {
      "name": "required",
      "type": "boolean",
      "required": false,
      "description": "Marks the control required for native form semantics."
    },
    {
      "name": "invalid",
      "type": "boolean",
      "required": false,
      "description": "Paints the invalid treatment and announces the control as invalid. A Field supplies\nthis from its own `error`; set it directly only for a control with no Field around it."
    },
    {
      "name": "ariaDescribedBy",
      "type": "string",
      "required": false,
      "description": "Ids of the helper or error copy describing the control, supplied by a parent Field."
    },
    {
      "name": "ariaLabelledBy",
      "type": "string",
      "required": false,
      "description": "Id of the visible label naming the control, supplied by a parent Field."
    },
    {
      "name": "value",
      "type": "string",
      "required": true,
      "description": "Current field value (controlled)."
    },
    {
      "name": "onChange",
      "type": "(value: string) => void",
      "required": false,
      "description": "Called with the next value on each edit."
    },
    {
      "name": "onEnter",
      "type": "() => void",
      "required": false,
      "description": "Called when Enter is pressed while focused."
    },
    {
      "name": "enterBehavior",
      "type": "InputEnterBehavior",
      "required": false,
      "description": "Return-key behavior. `advance` moves focus to the next compatible form\ncontrol before falling back to `onEnter`."
    },
    {
      "name": "enterKeyHint",
      "type": "InputEnterKeyHint",
      "required": false,
      "description": "Native on-screen keyboard return key hint."
    },
    {
      "name": "placeholder",
      "type": "string",
      "required": false,
      "description": "Placeholder text. Falls back to a wording keyed off `type`; `text` and `date` have none."
    },
    {
      "name": "size",
      "type": "InputSize",
      "required": false,
      "description": "Field size. Defaults to `md` for backwards-compatible form density."
    },
    {
      "name": "type",
      "type": "InputType",
      "required": false,
      "description": "Native input type, which also picks the default placeholder. `search` additionally defaults\n`enterBehavior` to `callback`, so its return key submits instead of moving focus."
    },
    {
      "name": "surface",
      "type": "InputSurface",
      "required": false,
      "description": "Container background treatment; use `raised` on cream canvases."
    },
    {
      "name": "ariaLabel",
      "type": "string",
      "required": false,
      "description": "Accessible name when no visible label is associated with the field."
    },
    {
      "name": "ariaControls",
      "type": "string",
      "required": false,
      "description": "ID of an associated popup/list controlled by this input."
    },
    {
      "name": "inputMode",
      "type": "React.InputHTMLAttributes<HTMLInputElement>['inputMode']",
      "required": false,
      "description": "On-screen keyboard hint (e.g. `numeric` for SSN/phone fields)."
    },
    {
      "name": "maxLength",
      "type": "number",
      "required": false,
      "description": "Native character-count limit on typed input."
    },
    {
      "name": "autoComplete",
      "type": "string",
      "required": false,
      "description": "Native autocomplete hint."
    },
    {
      "name": "autoCorrect",
      "type": "'on' | 'off'",
      "required": false,
      "description": "Native autocorrect hint."
    },
    {
      "name": "autoCapitalize",
      "type": "'off' | 'none' | 'on' | 'sentences' | 'words' | 'characters'",
      "required": false,
      "description": "Native autocapitalize hint."
    },
    {
      "name": "spellCheck",
      "type": "boolean",
      "required": false,
      "description": "Native spellcheck hint."
    },
    {
      "name": "name",
      "type": "string",
      "required": false,
      "description": "Form field name."
    },
    {
      "name": "readOnly",
      "type": "boolean",
      "required": false,
      "description": "Prevents editing while preserving focus and form submission semantics."
    },
    {
      "name": "min",
      "type": "React.InputHTMLAttributes<HTMLInputElement>['min']",
      "required": false,
      "description": "Native minimum value constraint."
    },
    {
      "name": "max",
      "type": "React.InputHTMLAttributes<HTMLInputElement>['max']",
      "required": false,
      "description": "Native maximum value constraint."
    },
    {
      "name": "step",
      "type": "React.InputHTMLAttributes<HTMLInputElement>['step']",
      "required": false,
      "description": "Native numeric step constraint."
    },
    {
      "name": "pattern",
      "type": "string",
      "required": false,
      "description": "Native validation pattern."
    },
    {
      "name": "leading",
      "type": "React.ReactNode",
      "required": false,
      "description": "Optional leading content inside the field shell."
    },
    {
      "name": "trailing",
      "type": "React.ReactNode",
      "required": false,
      "description": "Optional trailing content inside the field shell."
    },
    {
      "name": "trailingAction",
      "type": "React.ReactNode",
      "required": false,
      "description": "Optional trailing action inside the field shell."
    },
    {
      "name": "onFocus",
      "type": "() => void",
      "required": false,
      "description": "Called when the field gains focus."
    },
    {
      "name": "onBlur",
      "type": "() => void",
      "required": false,
      "description": "Called on blur, before any return-key advance moves focus on to the next control."
    },
    {
      "name": "className",
      "type": "string",
      "required": false,
      "description": "Class hook for the field wrapper."
    },
    {
      "name": "style",
      "type": "React.CSSProperties",
      "required": false,
      "description": "Inline style override for the field wrapper."
    },
    {
      "name": "testId",
      "type": "string",
      "required": false,
      "description": "Optional test selector. Lands on the `<input>`."
    }
  ],
  "prop_shapes": {},
  "examples": [
    {
      "id": "input-playground",
      "title": "Field and Input playground",
      "source": "packages/design-system/examples/InputPlayground.tsx",
      "export": "InputPlayground",
      "components": [
        "field",
        "input"
      ],
      "description": "A real controlled input with a connected label, helper text, error and disabled state.",
      "synthetic_data": true,
      "storybook_id": "components-field-and-input--playground",
      "code": "import { useState } from 'react';\nimport { Field, Input } from '../src';\nimport { DemoFrame, SelectControl } from './DemoFrame';\nimport { inputExampleCode, type InputExampleProps } from './code';\n\nexport function InputPlayground() {\n  const [email, setEmail] = useState('');\n  const [size, setSize] = useState<InputExampleProps['size']>('md');\n  const [state, setState] = useState<InputExampleProps['state']>('default');\n  const error = state === 'invalid' ? 'Enter an email address, such as name@example.com.' : undefined;\n  return <DemoFrame code={inputExampleCode({ size, state })} controls={<>\n    <SelectControl label=\"Size\" value={size} options={['md', 'sm']} onChange={value => setSize(value as InputExampleProps['size'])} />\n    <SelectControl label=\"State\" value={state} options={['default', 'invalid', 'disabled']} onChange={value => setState(value as InputExampleProps['state'])} />\n  </>}>\n    <div className=\"demo-input-stage\">\n      <Field label=\"Email address\" helperText=\"Use the address you check regularly.\" error={error} disabled={state === 'disabled'}>\n        <Input type=\"email\" size={size} value={email} onChange={setEmail} autoComplete=\"email\" />\n      </Field>\n    </div>\n  </DemoFrame>;\n}\n"
    },
    {
      "id": "protected-email-flow",
      "title": "Create a protected email",
      "source": "packages/design-system/examples/ProtectedEmailFlow.tsx",
      "export": "ProtectedEmailFlow",
      "components": [
        "button",
        "field",
        "input"
      ],
      "description": "A local-only sample flow with validation, loading, success and restart. No data is sent or saved.",
      "synthetic_data": true,
      "storybook_id": "patterns-protected-email--create",
      "code": "import { useEffect, useLayoutEffect, useRef, useState, type FormEvent } from 'react';\nimport { Button, Field, Input } from '../src';\nimport { DemoFrame } from './DemoFrame';\nimport { createSampleIdentity, validateIdentity, type IdentityDraft, type IdentityErrors } from './protected-email';\n\nconst EMPTY_DRAFT: IdentityDraft = { name: '', website: '' };\n\nexport function ProtectedEmailFlow() {\n  const [draft, setDraft] = useState<IdentityDraft>(EMPTY_DRAFT);\n  const [errors, setErrors] = useState<IdentityErrors>({});\n  const [stage, setStage] = useState<'editing' | 'loading' | 'success'>('editing');\n  const form = useRef<HTMLFormElement>(null);\n  const success = useRef<HTMLHeadingElement>(null);\n  useEffect(() => {\n    if (stage !== 'loading') return;\n    const timer = window.setTimeout(() => setStage('success'), 700);\n    return () => window.clearTimeout(timer);\n  }, [stage]);\n  useEffect(() => { if (stage === 'success') success.current?.focus(); }, [stage]);\n  useLayoutEffect(() => {\n    if (Object.keys(errors).length) form.current?.querySelector<HTMLInputElement>('[aria-invalid=\"true\"]')?.focus();\n  }, [errors]);\n  const restart = () => {\n    setDraft(EMPTY_DRAFT); setErrors({}); setStage('editing');\n    requestAnimationFrame(() => form.current?.querySelector<HTMLInputElement>('input')?.focus());\n  };\n  const submit = (event: FormEvent) => {\n    event.preventDefault();\n    if (stage !== 'editing') return;\n    const nextErrors = validateIdentity(draft);\n    setErrors(nextErrors);\n    if (Object.keys(nextErrors).length) return;\n    setStage('loading');\n  };\n  return <DemoFrame><section className=\"demo-flow\" aria-label=\"Create a protected email example\">\n    <p className=\"demo-sample-note\">Interactive example · Sample data only. Nothing is sent or saved.</p>\n    {stage === 'success' ? <FlowSuccess draft={draft} headingRef={success} restart={restart} /> :\n      <form ref={form} noValidate onSubmit={submit} aria-busy={stage === 'loading'}>\n        <FlowHeading />\n        <FlowFields draft={draft} errors={errors} loading={stage === 'loading'} change={setDraft} submit={() => form.current?.requestSubmit()} />\n        <Button variant=\"primary\" size=\"md\" fullWidth loading={stage === 'loading'} onPress={() => form.current?.requestSubmit()}>Create protected email</Button>\n        <p className=\"demo-feedback\" role=\"status\">{stage === 'loading' ? 'Creating your sample address…' : 'Your personal email stays yours.'}</p>\n      </form>}\n  </section></DemoFrame>;\n}\n\nfunction FlowHeading() {\n  return <div className=\"demo-flow-heading\">\n    <span className=\"demo-symbol\" aria-hidden=\"true\">@</span>\n    <span className=\"demo-eyebrow\">A little more privacy</span>\n    <h2>An email for this part of your life.</h2>\n    <p>Give it a name so you know where you used it.</p>\n  </div>;\n}\n\nfunction FlowFields({ draft, errors, loading, change, submit }: {\n  draft: IdentityDraft; errors: IdentityErrors; loading: boolean;\n  change: (draft: IdentityDraft) => void; submit: () => void;\n}) {\n  return <div className=\"demo-flow-fields\">\n    <Field label=\"Name\" helperText=\"For example, shopping or a newsletter.\" error={errors.name} required disabled={loading}>\n      <Input value={draft.name} onChange={name => change({ ...draft, name })} placeholder=\"Shopping\"\n        name=\"identity-name\" autoComplete=\"off\" maxLength={80} enterKeyHint=\"next\" />\n    </Field>\n    <Field label=\"Website (optional)\" helperText=\"A reminder of where you'll use this address.\" error={errors.website} disabled={loading}>\n      <Input value={draft.website} onChange={website => change({ ...draft, website })} placeholder=\"example.com\"\n        name=\"identity-website\" autoComplete=\"off\" inputMode=\"url\" autoCapitalize=\"none\" maxLength={200}\n        enterKeyHint=\"done\" enterBehavior=\"callback\" onEnter={submit} />\n    </Field>\n  </div>;\n}\n\nfunction FlowSuccess({ draft, headingRef, restart }: {\n  draft: IdentityDraft; headingRef: React.RefObject<HTMLHeadingElement>; restart: () => void;\n}) {\n  const identity = createSampleIdentity(draft);\n  return <div className=\"demo-flow-success\">\n    <span className=\"demo-symbol demo-symbol-success\" aria-hidden=\"true\">✓</span>\n    <span className=\"demo-eyebrow\">Ready to use</span>\n    <h2 ref={headingRef} tabIndex={-1}>A fresh address for {identity.name}.</h2>\n    <p>This sample address demonstrates the result. It cannot receive email.</p>\n    <div className=\"demo-email-result\"><span>Protected email</span><strong>{identity.email}</strong></div>\n    <Button variant=\"secondary\" size=\"md\" fullWidth onPress={restart}>Try the flow again</Button>\n  </div>;\n}\n"
    },
    {
      "id": "foundation-surfaces",
      "title": "Surfaces",
      "source": "packages/design-system/examples/foundations/FoundationSurfaces.tsx",
      "export": "FoundationSurfaces",
      "components": [
        "field",
        "input"
      ],
      "description": "Theme-aware page, card, and real Input layers plus an appropriately paired inverse surface.",
      "synthetic_data": true,
      "storybook_id": "foundations-surfaces--explore",
      "code": "import { useState } from 'react';\nimport { Field, Input, Text } from '../../src';\nimport { FoundationFrame } from './FoundationShared';\n\nexport function FoundationSurfaces() {\n  const [name, setName] = useState('Shopping');\n  return <FoundationFrame code={`const page = { background: 'var(--cds-bg-page)', color: 'var(--cds-text-primary)' };\\nconst card = { background: 'var(--cds-bg-surface)' };\\nconst inverse = { background: 'var(--cds-bg-inverse)', color: 'var(--cds-text-inverse)' };`}>\n    <div className=\"foundation-surface-page\">\n      <code>--cds-bg-page</code>\n      <div className=\"foundation-surface-card\">\n        <code>--cds-bg-surface</code>\n        <Text as=\"h2\" variant=\"h3-serif\">Give your address a home.</Text>\n        <Field label=\"Address name\" helperText=\"A useful label makes it easier to find later.\">\n          <Input value={name} onChange={setName} placeholder=\"Shopping\" autoComplete=\"off\" />\n        </Field>\n        <code>Input → --cds-input-container</code>\n      </div>\n    </div>\n    <div className=\"foundation-surface-inverse\" data-testid=\"surface-inverse\" style={{ background: 'var(--cds-bg-inverse)', color: 'var(--cds-text-inverse)' }}>\n      <div><span className=\"demo-eyebrow\">A deliberate change of context</span><Text as=\"h2\" variant=\"h3-serif\">Private feels different.</Text></div>\n      <code>--cds-bg-inverse + --cds-text-inverse</code>\n    </div>\n    <p className=\"foundation-caption\">Page, card, and input surfaces adapt to the selected theme. An inverse surface stays dark and keeps its own light foreground in both themes.</p>\n  </FoundationFrame>;\n}\n"
    }
  ],
  "tokens": [
    {
      "name": "--cds-size-40",
      "light": "40px",
      "dark": "40px"
    },
    {
      "name": "--cds-size-56",
      "light": "56px",
      "dark": "56px"
    },
    {
      "name": "--cds-space-8",
      "light": "8px",
      "dark": "8px"
    },
    {
      "name": "--cds-type-body-size",
      "light": "1rem",
      "dark": "1rem"
    },
    {
      "name": "--cds-type-body-small-size",
      "light": "0.875rem",
      "dark": "0.875rem"
    },
    {
      "name": "--cds-input-container",
      "light": "#f3f1ed",
      "dark": "#232321"
    },
    {
      "name": "--cds-bg-surface",
      "light": "#ffffff",
      "dark": "#1b1b18"
    },
    {
      "name": "--cds-text-primary",
      "light": "#141410",
      "dark": "#f3f1ed"
    },
    {
      "name": "--cds-text-secondary",
      "light": "#646260",
      "dark": "#ffffff99"
    },
    {
      "name": "--cds-text-danger",
      "light": "#b83100",
      "dark": "color-mix(in srgb, #b83100 60%, #ffffff)"
    }
  ],
  "visual_reference": {
    "stories": [
      {
        "id": "cloaked-design-system-primitives-input--playground",
        "name": "Playground",
        "title": "Cloaked Design System/Primitives/Input",
        "exportName": "Playground",
        "source_path": "packages/design-system/src/components/primitives/Input/Input.stories.tsx",
        "source_digest": "fa5d0501c9c65ff82eb830653806b66532abdbac2ff3fe9da04c5258dff0db4f",
        "status": "preview",
        "local_url": "/storybook/iframe.html?id=cloaked-design-system-primitives-input--playground&viewMode=story"
      },
      {
        "id": "cloaked-design-system-primitives-input--state-matrix",
        "name": "State Matrix",
        "title": "Cloaked Design System/Primitives/Input",
        "exportName": "StateMatrix",
        "source_path": "packages/design-system/src/components/primitives/Input/Input.stories.tsx",
        "source_digest": "fa5d0501c9c65ff82eb830653806b66532abdbac2ff3fe9da04c5258dff0db4f",
        "status": "preview",
        "local_url": "/storybook/iframe.html?id=cloaked-design-system-primitives-input--state-matrix&viewMode=story"
      },
      {
        "id": "cloaked-design-system-primitives-input--focused",
        "name": "Focused",
        "title": "Cloaked Design System/Primitives/Input",
        "exportName": "Focused",
        "source_path": "packages/design-system/src/components/primitives/Input/Input.stories.tsx",
        "source_digest": "fa5d0501c9c65ff82eb830653806b66532abdbac2ff3fe9da04c5258dff0db4f",
        "status": "preview",
        "local_url": "/storybook/iframe.html?id=cloaked-design-system-primitives-input--focused&viewMode=story"
      },
      {
        "id": "cloaked-design-system-primitives-input--types",
        "name": "Types",
        "title": "Cloaked Design System/Primitives/Input",
        "exportName": "Types",
        "source_path": "packages/design-system/src/components/primitives/Input/Input.stories.tsx",
        "source_digest": "fa5d0501c9c65ff82eb830653806b66532abdbac2ff3fe9da04c5258dff0db4f",
        "status": "preview",
        "local_url": "/storybook/iframe.html?id=cloaked-design-system-primitives-input--types&viewMode=story"
      },
      {
        "id": "cloaked-design-system-primitives-input--with-slots",
        "name": "With Slots",
        "title": "Cloaked Design System/Primitives/Input",
        "exportName": "WithSlots",
        "source_path": "packages/design-system/src/components/primitives/Input/Input.stories.tsx",
        "source_digest": "fa5d0501c9c65ff82eb830653806b66532abdbac2ff3fe9da04c5258dff0db4f",
        "status": "preview",
        "local_url": "/storybook/iframe.html?id=cloaked-design-system-primitives-input--with-slots&viewMode=story"
      },
      {
        "id": "cloaked-design-system-primitives-input--invalid-in-field",
        "name": "Invalid In Field",
        "title": "Cloaked Design System/Primitives/Input",
        "exportName": "InvalidInField",
        "source_path": "packages/design-system/src/components/primitives/Input/Input.stories.tsx",
        "source_digest": "fa5d0501c9c65ff82eb830653806b66532abdbac2ff3fe9da04c5258dff0db4f",
        "status": "preview",
        "local_url": "/storybook/iframe.html?id=cloaked-design-system-primitives-input--invalid-in-field&viewMode=story"
      },
      {
        "id": "cloaked-design-system-primitives-input--raised-on-canvas",
        "name": "Raised On Canvas",
        "title": "Cloaked Design System/Primitives/Input",
        "exportName": "RaisedOnCanvas",
        "source_path": "packages/design-system/src/components/primitives/Input/Input.stories.tsx",
        "source_digest": "fa5d0501c9c65ff82eb830653806b66532abdbac2ff3fe9da04c5258dff0db4f",
        "status": "preview",
        "local_url": "/storybook/iframe.html?id=cloaked-design-system-primitives-input--raised-on-canvas&viewMode=story"
      },
      {
        "id": "cloaked-design-system-primitives-input--mobile-form-flow",
        "name": "Mobile Form Flow",
        "title": "Cloaked Design System/Primitives/Input",
        "exportName": "MobileFormFlow",
        "source_path": "packages/design-system/src/components/primitives/Input/Input.stories.tsx",
        "source_digest": "fa5d0501c9c65ff82eb830653806b66532abdbac2ff3fe9da04c5258dff0db4f",
        "status": "preview",
        "local_url": "/storybook/iframe.html?id=cloaked-design-system-primitives-input--mobile-form-flow&viewMode=story"
      },
      {
        "id": "cloaked-design-system-primitives-input--dark-theme",
        "name": "Dark Theme",
        "title": "Cloaked Design System/Primitives/Input",
        "exportName": "DarkTheme",
        "source_path": "packages/design-system/src/components/primitives/Input/Input.stories.tsx",
        "source_digest": "fa5d0501c9c65ff82eb830653806b66532abdbac2ff3fe9da04c5258dff0db4f",
        "status": "preview",
        "local_url": "/storybook/iframe.html?id=cloaked-design-system-primitives-input--dark-theme&viewMode=story"
      }
    ],
    "name": "Input",
    "id": "input",
    "category": "Primitives"
  },
  "stories": [
    {
      "id": "cloaked-design-system-primitives-input--playground",
      "name": "Playground",
      "title": "Cloaked Design System/Primitives/Input",
      "exportName": "Playground",
      "source_path": "packages/design-system/src/components/primitives/Input/Input.stories.tsx",
      "source_digest": "fa5d0501c9c65ff82eb830653806b66532abdbac2ff3fe9da04c5258dff0db4f",
      "status": "preview",
      "local_url": "/storybook/iframe.html?id=cloaked-design-system-primitives-input--playground&viewMode=story"
    },
    {
      "id": "cloaked-design-system-primitives-input--state-matrix",
      "name": "State Matrix",
      "title": "Cloaked Design System/Primitives/Input",
      "exportName": "StateMatrix",
      "source_path": "packages/design-system/src/components/primitives/Input/Input.stories.tsx",
      "source_digest": "fa5d0501c9c65ff82eb830653806b66532abdbac2ff3fe9da04c5258dff0db4f",
      "status": "preview",
      "local_url": "/storybook/iframe.html?id=cloaked-design-system-primitives-input--state-matrix&viewMode=story"
    },
    {
      "id": "cloaked-design-system-primitives-input--focused",
      "name": "Focused",
      "title": "Cloaked Design System/Primitives/Input",
      "exportName": "Focused",
      "source_path": "packages/design-system/src/components/primitives/Input/Input.stories.tsx",
      "source_digest": "fa5d0501c9c65ff82eb830653806b66532abdbac2ff3fe9da04c5258dff0db4f",
      "status": "preview",
      "local_url": "/storybook/iframe.html?id=cloaked-design-system-primitives-input--focused&viewMode=story"
    },
    {
      "id": "cloaked-design-system-primitives-input--types",
      "name": "Types",
      "title": "Cloaked Design System/Primitives/Input",
      "exportName": "Types",
      "source_path": "packages/design-system/src/components/primitives/Input/Input.stories.tsx",
      "source_digest": "fa5d0501c9c65ff82eb830653806b66532abdbac2ff3fe9da04c5258dff0db4f",
      "status": "preview",
      "local_url": "/storybook/iframe.html?id=cloaked-design-system-primitives-input--types&viewMode=story"
    },
    {
      "id": "cloaked-design-system-primitives-input--with-slots",
      "name": "With Slots",
      "title": "Cloaked Design System/Primitives/Input",
      "exportName": "WithSlots",
      "source_path": "packages/design-system/src/components/primitives/Input/Input.stories.tsx",
      "source_digest": "fa5d0501c9c65ff82eb830653806b66532abdbac2ff3fe9da04c5258dff0db4f",
      "status": "preview",
      "local_url": "/storybook/iframe.html?id=cloaked-design-system-primitives-input--with-slots&viewMode=story"
    },
    {
      "id": "cloaked-design-system-primitives-input--invalid-in-field",
      "name": "Invalid In Field",
      "title": "Cloaked Design System/Primitives/Input",
      "exportName": "InvalidInField",
      "source_path": "packages/design-system/src/components/primitives/Input/Input.stories.tsx",
      "source_digest": "fa5d0501c9c65ff82eb830653806b66532abdbac2ff3fe9da04c5258dff0db4f",
      "status": "preview",
      "local_url": "/storybook/iframe.html?id=cloaked-design-system-primitives-input--invalid-in-field&viewMode=story"
    },
    {
      "id": "cloaked-design-system-primitives-input--raised-on-canvas",
      "name": "Raised On Canvas",
      "title": "Cloaked Design System/Primitives/Input",
      "exportName": "RaisedOnCanvas",
      "source_path": "packages/design-system/src/components/primitives/Input/Input.stories.tsx",
      "source_digest": "fa5d0501c9c65ff82eb830653806b66532abdbac2ff3fe9da04c5258dff0db4f",
      "status": "preview",
      "local_url": "/storybook/iframe.html?id=cloaked-design-system-primitives-input--raised-on-canvas&viewMode=story"
    },
    {
      "id": "cloaked-design-system-primitives-input--mobile-form-flow",
      "name": "Mobile Form Flow",
      "title": "Cloaked Design System/Primitives/Input",
      "exportName": "MobileFormFlow",
      "source_path": "packages/design-system/src/components/primitives/Input/Input.stories.tsx",
      "source_digest": "fa5d0501c9c65ff82eb830653806b66532abdbac2ff3fe9da04c5258dff0db4f",
      "status": "preview",
      "local_url": "/storybook/iframe.html?id=cloaked-design-system-primitives-input--mobile-form-flow&viewMode=story"
    },
    {
      "id": "cloaked-design-system-primitives-input--dark-theme",
      "name": "Dark Theme",
      "title": "Cloaked Design System/Primitives/Input",
      "exportName": "DarkTheme",
      "source_path": "packages/design-system/src/components/primitives/Input/Input.stories.tsx",
      "source_digest": "fa5d0501c9c65ff82eb830653806b66532abdbac2ff3fe9da04c5258dff0db4f",
      "status": "preview",
      "local_url": "/storybook/iframe.html?id=cloaked-design-system-primitives-input--dark-theme&viewMode=story"
    }
  ],
  "stories_source": {
    "path": "packages/design-system/src/components/primitives/Input/Input.stories.tsx",
    "code": "import React, { useEffect, useRef, useState } from 'react';\nimport type { Meta, StoryObj } from '@storybook/react-vite';\nimport { VStack } from '../../layout/VStack/VStack';\nimport { Field } from '../../forms/Field/Field';\nimport { Button } from '../Button/Button';\nimport { Icon } from '../Icon/Icon';\nimport { disabledControl, selectArgType } from '../../../storybook/controlOptions';\nimport {\n    Input,\n    type InputEnterBehavior,\n    type InputEnterKeyHint,\n    type InputProps,\n    type InputSurface,\n    type InputType,\n} from './Input';\nimport { FullMobileContactForm } from './Input.stories.fixtures';\n\nconst INPUT_TYPES = [\n    'text',\n    'password',\n    'email',\n    'tel',\n    'url',\n    'search',\n    'number',\n] as const satisfies readonly InputType[];\nconst INPUT_SURFACES = ['default', 'raised'] as const satisfies readonly InputSurface[];\nconst INPUT_ENTER_BEHAVIORS = ['advance', 'callback'] as const satisfies readonly InputEnterBehavior[];\nconst INPUT_ENTER_KEY_HINTS = [\n    'enter',\n    'done',\n    'go',\n    'next',\n    'previous',\n    'search',\n    'send',\n] as const satisfies readonly InputEnterKeyHint[];\n\nconst meta: Meta<typeof Input> = {\n    title: 'Cloaked Design System/Primitives/Input',\n    component: Input,\n    parameters: {\n        a11y: { test: 'error' },\n        stage: 'form-control',\n        docs: {\n            description: {\n                component:\n                    'The single-line text field, and nothing else — no label, no helper, no error message. ' +\n                    'Drive its `type` for the right native keyboard and validation (`email`, `tel`, `url`, ' +\n                    '`number`, `search`, `password`), and set `enterKeyHint` + `enterBehavior` for iOS ' +\n                    'return-key flow between fields. Wrap it in `Field` for a label and validation copy; the ' +\n                    \"Field's `error` turns this red on its own. Use `Textarea` for multi-line and \" +\n                    '`SearchField` for the search chrome.',\n            },\n        },\n    },\n    decorators: [\n        Story => (\n            <div style={{ width: '100%', maxWidth: 354 }}>\n                <Story />\n            </div>\n        ),\n    ],\n    args: {\n        placeholder: 'xxxx',\n        ariaLabel: 'Example field',\n        onChange: () => {},\n    },\n    argTypes: {\n        type: {\n            ...selectArgType(INPUT_TYPES),\n            description: 'Native input type; picks the on-screen keyboard and native validation.',\n        },\n        surface: {\n            ...selectArgType(INPUT_SURFACES),\n            description:\n                'Container fill. `default` is cream, for the white surfaces forms normally sit on; ' +\n                '`raised` is white, for a field placed directly on the cream page canvas.',\n        },\n        enterBehavior: {\n            ...selectArgType(INPUT_ENTER_BEHAVIORS),\n            description: '`advance` moves focus to the next form control before falling back to `onEnter`.',\n        },\n        enterKeyHint: {\n            ...selectArgType(INPUT_ENTER_KEY_HINTS),\n            description: 'Return-key label hint shown on the native on-screen keyboard.',\n        },\n        invalid: {\n            control: 'boolean',\n            description: 'Paints the invalid ring. A parent Field sets this from its own `error`.',\n        },\n        onChange: { ...disabledControl, description: 'Called with the next value on each edit.' },\n        onEnter: { ...disabledControl, description: 'Called when Enter is pressed while focused.' },\n        leading: { ...disabledControl, description: 'Content inside the field shell before the input.' },\n        trailing: { ...disabledControl, description: 'Content inside the field shell after the input.' },\n        trailingAction: { ...disabledControl, description: 'Trailing interactive action (e.g. a clear button).' },\n    },\n};\nexport default meta;\ntype Story = StoryObj<typeof Input>;\n\n/** Focuses the rendered field on mount so the active states can be shown statically. */\nfunction FocusedInput(props: InputProps) {\n    const ref = useRef<HTMLDivElement>(null);\n\n    useEffect(() => {\n        ref.current?.querySelector('input')?.focus();\n    }, []);\n\n    return (\n        <div ref={ref}>\n            <Input {...props} />\n        </div>\n    );\n}\n\n/** Controlled wrapper so the Playground story accepts typed input. */\nfunction ControlledInput(args: InputProps) {\n    const [value, setValue] = useState('');\n    return <Input {...args} value={value} onChange={setValue} />;\n}\n\n/** Fully interactive, controlled field. */\nexport const Playground: Story = {\n    render: args => <ControlledInput {...args} />,\n    args: { placeholder: 'Type here…', testId: 'input-story-playground' },\n};\n\n/** Empty, filled, invalid, and disabled fields side by side. */\nexport const StateMatrix: Story = {\n    parameters: {\n        docs: {\n            description: {\n                story: 'Every resting state at once. `invalid` here is the standalone escape hatch — it paints the ring and sets `aria-invalid` but renders no text, so pair it with copy the user can read. Inside a `Field`, the error comes from the Field instead.',\n            },\n        },\n    },\n    render: () => (\n        <VStack gap={16}>\n            <Input value='' placeholder='Empty field' ariaLabel='Empty field' testId='input-story-matrix-empty' />\n            <Input value='User Input' ariaLabel='Filled field' testId='input-story-matrix-filled' />\n            <Input value='User Input' invalid ariaLabel='Invalid field' testId='input-story-matrix-invalid' />\n            <Input value='User Input' disabled ariaLabel='Disabled field' testId='input-story-matrix-disabled' />\n        </VStack>\n    ),\n};\n\n/** Focused, empty and filled. The native caret and active placeholder appear. */\nexport const Focused: Story = {\n    parameters: {\n        docs: {\n            description: {\n                story: 'Both fields focus on mount so the active treatment is visible without interaction; only the first keeps the real DOM focus.',\n            },\n        },\n    },\n    render: () => (\n        <VStack gap={16}>\n            <FocusedInput\n                value=''\n                placeholder='Empty field'\n                ariaLabel='Empty field'\n                testId='input-story-focused-empty'\n            />\n            <FocusedInput value='User Input' ariaLabel='Filled field' testId='input-story-focused-filled' />\n        </VStack>\n    ),\n};\n\n/** The `type` values that change more than the keyboard: masking, URL validation, numeric bounds. */\nexport const Types: Story = {\n    parameters: {\n        docs: {\n            description: {\n                story: '`password` masks the value, `url` validates it as a web address, and `number` honours `min`/`max`/`step` — shown read-only, which keeps the field focusable where `disabled` would not.',\n            },\n        },\n    },\n    render: () => (\n        <VStack gap={16}>\n            <Input value='hunter2' type='password' ariaLabel='Password' testId='input-story-type-password' />\n            <Input value='https://cloaked.com' type='url' ariaLabel='Website' testId='input-story-type-url' />\n            <Input\n                value='4'\n                type='number'\n                readOnly\n                min={1}\n                max={10}\n                step={1}\n                ariaLabel='Read-only number'\n                testId='input-story-type-number'\n            />\n        </VStack>\n    ),\n};\n\n/** Leading/trailing slots, and the compact `sm` tier below the default `md`. */\nexport const WithSlots: Story = {\n    parameters: {\n        docs: {\n            description: {\n                story: '`leading`, `trailing`, and `trailingAction` place icons, units, and compact actions inside the field shell. The second field is the `sm` tier (40px) against the default `md` (56px) above it.',\n            },\n        },\n    },\n    render: () => (\n        <VStack gap={16}>\n            <Input\n                value=''\n                placeholder='Search brokers'\n                ariaLabel='Search brokers'\n                testId='input-story-slots'\n                leading={<Icon name='search' size='small' />}\n                trailing={<span>12</span>}\n                trailingAction={\n                    <Button\n                        variant='link'\n                        size='sm'\n                        icon={<Icon name='close' size='small' />}\n                        ariaLabel='Clear'\n                        testId='input-story-slots-clear'\n                    />\n                }\n            />\n            <Input\n                value=''\n                type='search'\n                size='sm'\n                placeholder='Search Widget'\n                ariaLabel='Search Widget'\n                testId='input-story-search-small'\n                leading={<Icon name='search' size='small' />}\n            />\n        </VStack>\n    ),\n};\n\n/** The normal path: Field owns the message and the Input turns red on its own. */\nexport const InvalidInField: Story = {\n    argTypes: { invalid: disabledControl },\n    render: args => (\n        <Field label='Zip code' error='Enter a 5-digit zip code.'>\n            <Input {...args} />\n        </Field>\n    ),\n    args: { value: '021', testId: 'input-story-invalid-in-field' },\n};\n\n/** Raised surface: white container for sitting on a cream page canvas (e.g. inside a cream sheet). */\nexport const RaisedOnCanvas: Story = {\n    parameters: { stage: 'page' },\n    args: { value: 'User Input', surface: 'raised', testId: 'input-story-raised' },\n};\n\n/** Mobile return-key flow: `next` moves through fields and `done` submits on the terminal control. */\nexport const MobileFormFlow: Story = {\n    // The fixture owns its own fields, so the args panel would drive nothing. `value` stays\n    // only because InputProps requires it.\n    parameters: { controls: { disable: true } },\n    render: () => <FullMobileContactForm />,\n    args: { value: '' },\n};\n\n/** Dark theme rendering. */\nexport const DarkTheme: Story = {\n    args: { value: 'User Input', testId: 'input-story-dark' },\n    globals: { theme: 'dark' },\n};\n"
  },
  "platforms": {
    "implemented": [
      "web"
    ],
    "native": "Imported design guidance only; no native implementation or parity verification in this preview.",
    "react": {
      "implementation": "local",
      "status": "preview",
      "parity": "web-reference"
    },
    "vue": {
      "implementation": "absent",
      "parity": "not-verified",
      "status": "reference-only"
    },
    "swift": {
      "implementation": "absent",
      "parity": "not-verified",
      "status": "reference-only"
    },
    "kotlin": {
      "implementation": "absent",
      "parity": "not-verified",
      "status": "reference-only"
    }
  },
  "links": {
    "human": "/component-input",
    "json": "/data/components/input.json",
    "markdown": "/data/components/input.md",
    "storybook": "/storybook/?path=/story/cloaked-design-system-primitives-input--playground"
  },
  "contract_status": "preview",
  "contract_kind": "curated",
  "approval": "required",
  "api": {
    "method": "typescript-type-checker",
    "typescript_version": "5.9.3",
    "public_export": "Input",
    "public_path": "Input",
    "import_path": "@cloakedinc/design-system",
    "root_kind": "component",
    "entrypoints": [
      {
        "name": "Input",
        "signature": 1,
        "visibility": "public",
        "source": {
          "path": "packages/design-system/src/components/primitives/Input/Input.tsx",
          "line": 112
        },
        "props_type": "InputProps",
        "props": [
          {
            "name": "value",
            "type": "string",
            "declared_type": "string",
            "required": true,
            "description": "Current field value (controlled).",
            "source": {
              "path": "packages/design-system/src/components/primitives/Input/Input.tsx",
              "line": 36
            }
          },
          {
            "name": "onChange",
            "type": "((value: string) => void) | undefined",
            "declared_type": "(value: string) => void",
            "required": false,
            "description": "Called with the next value on each edit.",
            "source": {
              "path": "packages/design-system/src/components/primitives/Input/Input.tsx",
              "line": 38
            }
          },
          {
            "name": "onEnter",
            "type": "(() => void) | undefined",
            "declared_type": "() => void",
            "required": false,
            "description": "Called when Enter is pressed while focused.",
            "source": {
              "path": "packages/design-system/src/components/primitives/Input/Input.tsx",
              "line": 40
            }
          },
          {
            "name": "enterBehavior",
            "type": "InputEnterBehavior | undefined",
            "declared_type": "InputEnterBehavior",
            "required": false,
            "description": "Return-key behavior. `advance` moves focus to the next compatible form\ncontrol before falling back to `onEnter`.",
            "source": {
              "path": "packages/design-system/src/components/primitives/Input/Input.tsx",
              "line": 45
            },
            "values": [
              "advance",
              "callback"
            ],
            "values_complete": true
          },
          {
            "name": "enterKeyHint",
            "type": "InputEnterKeyHint | undefined",
            "declared_type": "InputEnterKeyHint",
            "required": false,
            "description": "Native on-screen keyboard return key hint.",
            "source": {
              "path": "packages/design-system/src/components/primitives/Input/Input.tsx",
              "line": 47
            },
            "values": [
              "done",
              "enter",
              "go",
              "next",
              "previous",
              "search",
              "send"
            ],
            "values_complete": true
          },
          {
            "name": "placeholder",
            "type": "string | undefined",
            "declared_type": "string",
            "required": false,
            "description": "Placeholder text. Falls back to a wording keyed off `type`; `text` and `date` have none.",
            "source": {
              "path": "packages/design-system/src/components/primitives/Input/Input.tsx",
              "line": 49
            }
          },
          {
            "name": "size",
            "type": "InputSize | undefined",
            "declared_type": "InputSize",
            "required": false,
            "description": "Field size. Defaults to `md` for backwards-compatible form density.",
            "source": {
              "path": "packages/design-system/src/components/primitives/Input/Input.tsx",
              "line": 51
            },
            "values": [
              "md",
              "sm"
            ],
            "values_complete": true,
            "default": "'md'",
            "default_kind": "source-expression"
          },
          {
            "name": "type",
            "type": "InputType | undefined",
            "declared_type": "InputType",
            "required": false,
            "description": "Native input type, which also picks the default placeholder. `search` additionally defaults\n`enterBehavior` to `callback`, so its return key submits instead of moving focus.",
            "source": {
              "path": "packages/design-system/src/components/primitives/Input/Input.tsx",
              "line": 56
            },
            "values": [
              "date",
              "email",
              "number",
              "password",
              "search",
              "tel",
              "text",
              "url"
            ],
            "values_complete": true,
            "default": "'text'",
            "default_kind": "source-expression"
          },
          {
            "name": "surface",
            "type": "InputSurface | undefined",
            "declared_type": "InputSurface",
            "required": false,
            "description": "Container background treatment; use `raised` on cream canvases.",
            "source": {
              "path": "packages/design-system/src/components/primitives/Input/Input.tsx",
              "line": 58
            },
            "values": [
              "default",
              "raised"
            ],
            "values_complete": true,
            "default": "'default'",
            "default_kind": "source-expression"
          },
          {
            "name": "disabled",
            "type": "boolean | undefined",
            "declared_type": "boolean",
            "required": false,
            "description": "Blocks editing and focus, and dims the field. Prefer `readOnly` to keep it focusable.",
            "source": {
              "path": "packages/design-system/src/components/primitives/Input/Input.tsx",
              "line": 60
            },
            "values": [
              false,
              true
            ],
            "values_complete": true
          },
          {
            "name": "ariaLabel",
            "type": "string | undefined",
            "declared_type": "string",
            "required": false,
            "description": "Accessible name when no visible label is associated with the field.",
            "source": {
              "path": "packages/design-system/src/components/primitives/Input/Input.tsx",
              "line": 62
            }
          },
          {
            "name": "ariaControls",
            "type": "string | undefined",
            "declared_type": "string",
            "required": false,
            "description": "ID of an associated popup/list controlled by this input.",
            "source": {
              "path": "packages/design-system/src/components/primitives/Input/Input.tsx",
              "line": 64
            }
          },
          {
            "name": "inputMode",
            "type": "\"search\" | \"email\" | \"none\" | \"text\" | \"tel\" | \"url\" | \"numeric\" | \"decimal\" | undefined",
            "declared_type": "React.InputHTMLAttributes<HTMLInputElement>['inputMode']",
            "required": false,
            "description": "On-screen keyboard hint (e.g. `numeric` for SSN/phone fields).",
            "source": {
              "path": "packages/design-system/src/components/primitives/Input/Input.tsx",
              "line": 66
            },
            "values": [
              "decimal",
              "email",
              "none",
              "numeric",
              "search",
              "tel",
              "text",
              "url"
            ],
            "values_complete": true
          },
          {
            "name": "maxLength",
            "type": "number | undefined",
            "declared_type": "number",
            "required": false,
            "description": "Native character-count limit on typed input.",
            "source": {
              "path": "packages/design-system/src/components/primitives/Input/Input.tsx",
              "line": 68
            }
          },
          {
            "name": "autoComplete",
            "type": "string | undefined",
            "declared_type": "string",
            "required": false,
            "description": "Native autocomplete hint.",
            "source": {
              "path": "packages/design-system/src/components/primitives/Input/Input.tsx",
              "line": 70
            }
          },
          {
            "name": "autoCorrect",
            "type": "\"on\" | \"off\" | undefined",
            "declared_type": "'on' | 'off'",
            "required": false,
            "description": "Native autocorrect hint.",
            "source": {
              "path": "packages/design-system/src/components/primitives/Input/Input.tsx",
              "line": 72
            },
            "values": [
              "off",
              "on"
            ],
            "values_complete": true
          },
          {
            "name": "autoCapitalize",
            "type": "\"none\" | \"on\" | \"off\" | \"sentences\" | \"words\" | \"characters\" | undefined",
            "declared_type": "'off' | 'none' | 'on' | 'sentences' | 'words' | 'characters'",
            "required": false,
            "description": "Native autocapitalize hint.",
            "source": {
              "path": "packages/design-system/src/components/primitives/Input/Input.tsx",
              "line": 74
            },
            "values": [
              "characters",
              "none",
              "off",
              "on",
              "sentences",
              "words"
            ],
            "values_complete": true
          },
          {
            "name": "spellCheck",
            "type": "boolean | undefined",
            "declared_type": "boolean",
            "required": false,
            "description": "Native spellcheck hint.",
            "source": {
              "path": "packages/design-system/src/components/primitives/Input/Input.tsx",
              "line": 76
            },
            "values": [
              false,
              true
            ],
            "values_complete": true
          },
          {
            "name": "name",
            "type": "string | undefined",
            "declared_type": "string",
            "required": false,
            "description": "Form field name.",
            "source": {
              "path": "packages/design-system/src/components/primitives/Input/Input.tsx",
              "line": 78
            }
          },
          {
            "name": "readOnly",
            "type": "boolean | undefined",
            "declared_type": "boolean",
            "required": false,
            "description": "Prevents editing while preserving focus and form submission semantics.",
            "source": {
              "path": "packages/design-system/src/components/primitives/Input/Input.tsx",
              "line": 80
            },
            "values": [
              false,
              true
            ],
            "values_complete": true
          },
          {
            "name": "min",
            "type": "string | number | undefined",
            "declared_type": "React.InputHTMLAttributes<HTMLInputElement>['min']",
            "required": false,
            "description": "Native minimum value constraint.",
            "source": {
              "path": "packages/design-system/src/components/primitives/Input/Input.tsx",
              "line": 82
            }
          },
          {
            "name": "max",
            "type": "string | number | undefined",
            "declared_type": "React.InputHTMLAttributes<HTMLInputElement>['max']",
            "required": false,
            "description": "Native maximum value constraint.",
            "source": {
              "path": "packages/design-system/src/components/primitives/Input/Input.tsx",
              "line": 84
            }
          },
          {
            "name": "step",
            "type": "string | number | undefined",
            "declared_type": "React.InputHTMLAttributes<HTMLInputElement>['step']",
            "required": false,
            "description": "Native numeric step constraint.",
            "source": {
              "path": "packages/design-system/src/components/primitives/Input/Input.tsx",
              "line": 86
            }
          },
          {
            "name": "pattern",
            "type": "string | undefined",
            "declared_type": "string",
            "required": false,
            "description": "Native validation pattern.",
            "source": {
              "path": "packages/design-system/src/components/primitives/Input/Input.tsx",
              "line": 88
            }
          },
          {
            "name": "leading",
            "type": "React.ReactNode",
            "declared_type": "React.ReactNode",
            "required": false,
            "description": "Optional leading content inside the field shell.",
            "source": {
              "path": "packages/design-system/src/components/primitives/Input/Input.tsx",
              "line": 90
            }
          },
          {
            "name": "trailing",
            "type": "React.ReactNode",
            "declared_type": "React.ReactNode",
            "required": false,
            "description": "Optional trailing content inside the field shell.",
            "source": {
              "path": "packages/design-system/src/components/primitives/Input/Input.tsx",
              "line": 92
            }
          },
          {
            "name": "trailingAction",
            "type": "React.ReactNode",
            "declared_type": "React.ReactNode",
            "required": false,
            "description": "Optional trailing action inside the field shell.",
            "source": {
              "path": "packages/design-system/src/components/primitives/Input/Input.tsx",
              "line": 94
            }
          },
          {
            "name": "onFocus",
            "type": "(() => void) | undefined",
            "declared_type": "() => void",
            "required": false,
            "description": "Called when the field gains focus.",
            "source": {
              "path": "packages/design-system/src/components/primitives/Input/Input.tsx",
              "line": 96
            }
          },
          {
            "name": "onBlur",
            "type": "(() => void) | undefined",
            "declared_type": "() => void",
            "required": false,
            "description": "Called on blur, before any return-key advance moves focus on to the next control.",
            "source": {
              "path": "packages/design-system/src/components/primitives/Input/Input.tsx",
              "line": 98
            }
          },
          {
            "name": "className",
            "type": "string | undefined",
            "declared_type": "string",
            "required": false,
            "description": "Class hook for the field wrapper.",
            "source": {
              "path": "packages/design-system/src/components/primitives/Input/Input.tsx",
              "line": 100
            }
          },
          {
            "name": "style",
            "type": "React.CSSProperties | undefined",
            "declared_type": "React.CSSProperties",
            "required": false,
            "description": "Inline style override for the field wrapper.",
            "source": {
              "path": "packages/design-system/src/components/primitives/Input/Input.tsx",
              "line": 102
            }
          },
          {
            "name": "testId",
            "type": "string | undefined",
            "declared_type": "string",
            "required": false,
            "description": "Optional test selector. Lands on the `<input>`.",
            "source": {
              "path": "packages/design-system/src/components/primitives/Input/Input.tsx",
              "line": 104
            }
          },
          {
            "name": "id",
            "type": "string | undefined",
            "declared_type": "string",
            "required": false,
            "description": "DOM id the control renders, which the Field's label points at.",
            "source": {
              "path": "packages/design-system/src/hooks/FieldContext.ts",
              "line": 22
            }
          },
          {
            "name": "required",
            "type": "boolean | undefined",
            "declared_type": "boolean",
            "required": false,
            "description": "Marks the control required for native form semantics.",
            "source": {
              "path": "packages/design-system/src/hooks/FieldContext.ts",
              "line": 26
            },
            "values": [
              false,
              true
            ],
            "values_complete": true
          },
          {
            "name": "invalid",
            "type": "boolean | undefined",
            "declared_type": "boolean",
            "required": false,
            "description": "Paints the invalid treatment and announces the control as invalid. A Field supplies\nthis from its own `error`; set it directly only for a control with no Field around it.",
            "source": {
              "path": "packages/design-system/src/hooks/FieldContext.ts",
              "line": 31
            },
            "values": [
              false,
              true
            ],
            "values_complete": true
          },
          {
            "name": "ariaDescribedBy",
            "type": "string | undefined",
            "declared_type": "string",
            "required": false,
            "description": "Ids of the helper or error copy describing the control, supplied by a parent Field.",
            "source": {
              "path": "packages/design-system/src/hooks/FieldContext.ts",
              "line": 33
            }
          },
          {
            "name": "ariaLabelledBy",
            "type": "string | undefined",
            "declared_type": "string",
            "required": false,
            "description": "Id of the visible label naming the control, supplied by a parent Field.",
            "source": {
              "path": "packages/design-system/src/hooks/FieldContext.ts",
              "line": 35
            }
          }
        ],
        "branches": [],
        "constraints": [],
        "extraction_status": "extracted"
      }
    ],
    "type_sources": [
      {
        "path": "packages/design-system/src/components/primitives/Input/Input.tsx",
        "line": 7,
        "name": "InputType",
        "code": "export type InputType = 'text' | 'password' | 'email' | 'tel' | 'url' | 'search' | 'number' | 'date';"
      },
      {
        "path": "packages/design-system/src/components/primitives/Input/Input.tsx",
        "line": 8,
        "name": "InputSize",
        "code": "export type InputSize = 'sm' | 'md';"
      },
      {
        "path": "packages/design-system/src/components/primitives/Input/Input.tsx",
        "line": 9,
        "name": "InputEnterBehavior",
        "code": "export type InputEnterBehavior = 'advance' | 'callback';"
      },
      {
        "path": "packages/design-system/src/components/primitives/Input/Input.tsx",
        "line": 10,
        "name": "InputEnterKeyHint",
        "code": "export type InputEnterKeyHint = 'enter' | 'done' | 'go' | 'next' | 'previous' | 'search' | 'send';"
      },
      {
        "path": "packages/design-system/src/components/primitives/Input/Input.tsx",
        "line": 28,
        "name": "InputSurface",
        "code": "export type InputSurface = 'default' | 'raised';"
      },
      {
        "path": "packages/design-system/src/components/primitives/Input/Input.tsx",
        "line": 34,
        "name": "InputProps",
        "code": "export interface InputProps extends FieldControlProps {\n    /** Current field value (controlled). */\n    value: string;\n    /** Called with the next value on each edit. */\n    onChange?: (value: string) => void;\n    /** Called when Enter is pressed while focused. */\n    onEnter?: () => void;\n    /**\n     * Return-key behavior. `advance` moves focus to the next compatible form\n     * control before falling back to `onEnter`.\n     */\n    enterBehavior?: InputEnterBehavior;\n    /** Native on-screen keyboard return key hint. */\n    enterKeyHint?: InputEnterKeyHint;\n    /** Placeholder text. Falls back to a wording keyed off `type`; `text` and `date` have none. */\n    placeholder?: string;\n    /** Field size. Defaults to `md` for backwards-compatible form density. */\n    size?: InputSize;\n    /**\n     * Native input type, which also picks the default placeholder. `search` additionally defaults\n     * `enterBehavior` to `callback`, so its return key submits instead of moving focus.\n     */\n    type?: InputType;\n    /** Container background treatment; use `raised` on cream canvases. */\n    surface?: InputSurface;\n    /** Blocks editing and focus, and dims the field. Prefer `readOnly` to keep it focusable. */\n    disabled?: boolean;\n    /** Accessible name when no visible label is associated with the field. */\n    ariaLabel?: string;\n    /** ID of an associated popup/list controlled by this input. */\n    ariaControls?: string;\n    /** On-screen keyboard hint (e.g. `numeric` for SSN/phone fields). */\n    inputMode?: React.InputHTMLAttributes<HTMLInputElement>['inputMode'];\n    /** Native character-count limit on typed input. */\n    maxLength?: number;\n    /** Native autocomplete hint. */\n    autoComplete?: string;\n    /** Native autocorrect hint. */\n    autoCorrect?: 'on' | 'off';\n    /** Native autocapitalize hint. */\n    autoCapitalize?: 'off' | 'none' | 'on' | 'sentences' | 'words' | 'characters';\n    /** Native spellcheck hint. */\n    spellCheck?: boolean;\n    /** Form field name. */\n    name?: string;\n    /** Prevents editing while preserving focus and form submission semantics. */\n    readOnly?: boolean;\n    /** Native minimum value constraint. */\n    min?: React.InputHTMLAttributes<HTMLInputElement>['min'];\n    /** Native maximum value constraint. */\n    max?: React.InputHTMLAttributes<HTMLInputElement>['max'];\n    /** Native numeric step constraint. */\n    step?: React.InputHTMLAttributes<HTMLInputElement>['step'];\n    /** Native validation pattern. */\n    pattern?: string;\n    /** Optional leading content inside the field shell. */\n    leading?: React.ReactNode;\n    /** Optional trailing content inside the field shell. */\n    trailing?: React.ReactNode;\n    /** Optional trailing action inside the field shell. */\n    trailingAction?: React.ReactNode;\n    /** Called when the field gains focus. */\n    onFocus?: () => void;\n    /** Called on blur, before any return-key advance moves focus on to the next control. */\n    onBlur?: () => void;\n    /** Class hook for the field wrapper. */\n    className?: string;\n    /** Inline style override for the field wrapper. */\n    style?: React.CSSProperties;\n    /** Optional test selector. Lands on the `<input>`. */\n    testId?: string;\n}"
      },
      {
        "path": "packages/design-system/src/hooks/FieldContext.ts",
        "line": 20,
        "name": "FieldControlProps",
        "code": "export interface FieldControlProps {\n    /** DOM id the control renders, which the Field's label points at. */\n    id?: string;\n    /** Blocks interaction and dims the control. */\n    disabled?: boolean;\n    /** Marks the control required for native form semantics. */\n    required?: boolean;\n    /**\n     * Paints the invalid treatment and announces the control as invalid. A Field supplies\n     * this from its own `error`; set it directly only for a control with no Field around it.\n     */\n    invalid?: boolean;\n    /** Ids of the helper or error copy describing the control, supplied by a parent Field. */\n    ariaDescribedBy?: string;\n    /** Id of the visible label naming the control, supplied by a parent Field. */\n    ariaLabelledBy?: string;\n}"
      }
    ],
    "defaults_policy": "Only explicit destructured parameter initializers are extracted. Other runtime defaults remain in implementation source."
  },
  "missing_facts": [
    {
      "code": "human-review-pending",
      "detail": "This local preview has no recorded human design or engineering sign-off."
    },
    {
      "code": "platform-parity-unverified",
      "detail": "Vue, Swift and Kotlin implementations are absent from this package; platform parity has not been verified."
    },
    {
      "code": "figma-mapping-unverified",
      "detail": "No current component-level Figma node and immutable revision have been verified for this contract."
    }
  ],
  "review": {
    "local_status": "not-reviewed",
    "source_approval": null,
    "imported_spec_status": "approved",
    "spec_origin": "imported-adapted",
    "local_spec_source_status": "preview",
    "imported_source_revision": "f96f416e1c3bfbfaffcd155a88b87b18b8bb25f1",
    "note": "Inherited specification status is provenance, not approval of the current local implementation or extracted contract."
  }
}
