{"$schema":"https://ui.shadcn.com/schema/registry-item.json","name":"input","type":"registry:ui","title":"Input","description":"A recessed text field with optional leading and trailing affixes; it never jumps when validation appears.","dependencies":["clsx","tailwind-merge"],"registryDependencies":["https://caliperui.site/r/styles.json"],"files":[{"path":"ui/input.tsx","type":"registry:ui","target":"components/ui/input.tsx","content":"import type { ComponentProps, ReactNode } from \"react\";\nimport { cn } from \"./lib/cn\";\nimport \"./shared/input.css\";\nimport \"./shared/input-2.css\";\nimport \"./shared/input-group.css\";\nimport \"./input.css\";\n\nconst fieldText =\n  \"w-full min-w-0 text-base text-foreground outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed md:text-sm\";\n\nexport type InputProps = ComponentProps<\"input\"> & {\n  /** Fixed text or an icon before the value, e.g. \"caliper.app/\". */\n  leading?: ReactNode;\n  /** Text, an icon or a status after the value, e.g. a spinner or a count. */\n  trailing?: ReactNode;\n};\n\n/**\n * A recessed text field. Fields sit slightly below the paper (an inner shade\n * and a 3:1 ring); buttons stand on it, so what you fill and what you press\n * never look alike.\n */\nexport function Input({ className, leading, trailing, ...props }: InputProps) {\n  if (leading === undefined && trailing === undefined) {\n    return (\n      <input\n        data-slot=\"input\"\n        className={cn(\"flex h-[var(--control-height)] rounded-button px-3\", fieldText, className)}\n        {...props}\n      />\n    );\n  }\n  return (\n    <span\n      data-slot=\"input-group\"\n      data-disabled={props.disabled || undefined}\n      data-invalid={props[\"aria-invalid\"] === true || props[\"aria-invalid\"] === \"true\" || undefined}\n      data-readonly={props.readOnly || undefined}\n      className={cn(\"flex h-[var(--control-height)] w-full min-w-0 items-center gap-2 rounded-button px-3\", className)}\n    >\n      {leading !== undefined && <span data-slot=\"input-affix\">{leading}</span>}\n      <input data-slot=\"input-bare\" className={cn(\"h-full flex-1 bg-transparent\", fieldText)} {...props} />\n      {trailing !== undefined && <span data-slot=\"input-trailing\">{trailing}</span>}\n    </span>\n  );\n}\n"},{"path":"ui/lib/cn.ts","type":"registry:ui","target":"components/ui/lib/cn.ts","content":"import { clsx, type ClassValue } from \"clsx\";\nimport { extendTailwindMerge } from \"tailwind-merge\";\n\nconst twMerge = extendTailwindMerge({\n  extend: { theme: { radius: [\"control\", \"surface\", \"overlay\"], shadow: [\"overlay\"] } },\n});\n\nexport function cn(...inputs: ClassValue[]) {\n  return twMerge(clsx(inputs));\n}\n"},{"path":"ui/shared/input.css","type":"registry:file","target":"components/ui/shared/input.css","content":"/* Shared by combobox.tsx, input.tsx; each imports it. Edit freely. */\n@layer theme, base, components, utilities;\n\n@layer components {\n  [data-slot=\"input\"] {\n    transition-property: background-color, color, border-color;\n    transition-duration: var(--duration-fast);\n    transition-timing-function: var(--ease-out);\n  }\n\n  /* Recessed to fill. One ring for every field: 3:1 at rest, darker on\n     hover, a 2px ember ring with a soft halo on focus, danger when invalid.\n     Disabled and read-only drop into the sunken fill and stay legible. */\n  [data-slot=\"input\"] {\n    border: 0;\n    background-color: var(--field);\n    box-shadow: var(--shadow-field);\n    transition: box-shadow var(--duration-fast) var(--ease-out);\n  }\n\n  @media (prefers-reduced-motion: reduce) {\n    [data-slot=\"input\"] {\n      transition: none;\n    }\n  }\n}\n"},{"path":"ui/shared/input-2.css","type":"registry:file","target":"components/ui/shared/input-2.css","content":"/* Shared by combobox.tsx, input.tsx, select-menu.tsx, select.tsx, textarea.tsx; each imports it. Edit freely. */\n@layer theme, base, components, utilities;\n\n@layer components {\n  @media (hover: hover) {\n    :is([data-slot=\"input\"], [data-slot=\"textarea\"], [data-slot=\"select\"]):hover:enabled:not(:focus-visible):not([aria-invalid=\"true\"]) {\n      box-shadow: var(--shadow-field-hover);\n    }\n  }\n  :is([data-slot=\"input\"], [data-slot=\"textarea\"], [data-slot=\"select\"]):focus-visible {\n    outline: none;\n    box-shadow: var(--shadow-field-focus);\n    transition: none;\n  }\n  :is([data-slot=\"input\"], [data-slot=\"textarea\"], [data-slot=\"select\"])[aria-invalid=\"true\"] {\n    box-shadow: var(--shadow-field-invalid);\n  }\n  :is([data-slot=\"input\"], [data-slot=\"textarea\"], [data-slot=\"select\"])[aria-invalid=\"true\"]:focus-visible {\n    box-shadow:\n      var(--shadow-field-invalid),\n      0 0 0 4px color-mix(in srgb, var(--danger) 18%, transparent);\n  }\n  :is([data-slot=\"input\"], [data-slot=\"textarea\"], [data-slot=\"select\"]):disabled {\n    background-color: var(--sunken);\n    box-shadow: var(--shadow-field-quiet);\n    color: var(--muted-foreground);\n  }\n  :is([data-slot=\"input\"], [data-slot=\"textarea\"])[readonly] {\n    background-color: var(--sunken);\n    box-shadow: var(--shadow-field-quiet);\n  }\n}\n"},{"path":"ui/shared/input-group.css","type":"registry:file","target":"components/ui/shared/input-group.css","content":"/* Shared by input.tsx, money-field.tsx, phone-field.tsx; each imports it. Edit freely. */\n@layer theme, base, components, utilities;\n\n@layer components {\n  @media (hover: hover) {\n    :is([data-slot=\"input-group\"], [data-slot=\"money-field\"], [data-slot=\"phone-field-control\"]):not([data-disabled]):not([data-invalid]):hover:not(:focus-within) {\n      box-shadow: var(--shadow-field-hover);\n    }\n  }\n  :is([data-slot=\"input-group\"], [data-slot=\"money-field\"], [data-slot=\"phone-field-control\"]):focus-within {\n    outline: none;\n    box-shadow: var(--shadow-field-focus);\n    transition: none;\n  }\n}\n"},{"path":"ui/input.css","type":"registry:file","target":"components/ui/input.css","content":"/* input.tsx's styles; it imports this file. Edit freely. */\n@layer theme, base, components, utilities;\n\n@layer components {\n  /* Recessed to fill. One ring for every field: 3:1 at rest, darker on\n     hover, a 2px ember ring with a soft halo on focus, danger when invalid.\n     Disabled and read-only drop into the sunken fill and stay legible. */\n  [data-slot=\"input-group\"] {\n    border: 0;\n    background-color: var(--field);\n    box-shadow: var(--shadow-field);\n    transition: box-shadow var(--duration-fast) var(--ease-out);\n  }\n  [data-slot=\"input-group\"][data-invalid] {\n    box-shadow: var(--shadow-field-invalid);\n  }\n  [data-slot=\"input-group\"][data-invalid]:focus-within {\n    box-shadow:\n      var(--shadow-field-invalid),\n      0 0 0 4px color-mix(in srgb, var(--danger) 18%, transparent);\n  }\n  [data-slot=\"input-group\"][data-disabled] {\n    background-color: var(--sunken);\n    box-shadow: var(--shadow-field-quiet);\n    color: var(--muted-foreground);\n  }\n  [data-slot=\"input-group\"][data-readonly] {\n    background-color: var(--sunken);\n    box-shadow: var(--shadow-field-quiet);\n  }\n  [data-slot=\"input-bare\"] {\n    border: 0;\n    box-shadow: none;\n    outline: none;\n  }\n  [data-slot=\"input-affix\"] {\n    display: inline-flex;\n    align-items: center;\n    height: 20px;\n    padding-inline-end: 10px;\n    margin-inline-end: 2px;\n    color: var(--muted-foreground);\n    box-shadow: 1px 0 0 var(--border);\n    white-space: nowrap;\n  }\n  [data-slot=\"input-affix\"]:dir(rtl) {\n    box-shadow: -1px 0 0 var(--border);\n  }\n  [data-slot=\"input-affix\"]:has(> svg:only-child) {\n    padding-inline-end: 0;\n    box-shadow: none;\n  }\n  [data-slot=\"input-trailing\"] {\n    display: inline-flex;\n    align-items: center;\n    gap: 6px;\n    color: var(--muted-foreground);\n    white-space: nowrap;\n    font-size: 12px;\n  }\n  :is([data-slot=\"input-affix\"], [data-slot=\"input-trailing\"]) svg {\n    width: 16px;\n    height: 16px;\n  }\n  [data-slot=\"docs-toolbar\"] [data-slot=\"input-group\"] { max-width: 24rem; }\n}\n"}],"categories":["inputs"],"meta":{"tier":"free","license":"MIT","family":"inputs","docs":"/docs/components/input"}}