<!-- source-hash: 96e461088a5374855c0977550d1322c9 -->
A controlled search input component that combines inline tag chips with a text input, supporting automatic or fixed tag overflow with a popup for hidden tags.

## Key Components

### `TagSearchOption<T>`
Generic interface representing a selectable tag with a `label` string and typed `value`.

### `TagSearchInputProps<T>`
Full props interface for the component, including:
- `tags` / `searchValue` — controlled state inputs
- `onSearchChange` / `onTagRemove` / `onClearAll` — mutation callbacks
- `limitTags` — `number | "auto"` (default `"auto"`) controls visible tag count
- `renderTag` / `getLimitTagsText` — render customization slots
- `onSubmit` / `onKeyDown` — keyboard event hooks

### `TagSearchInput<T>`
The main generic component. Renders a styled input container with:
- **Visible tags** — rendered as `<Tag>` chips up to `visibleCount`
- **Overflow badge** — a `+N` button that toggles a `HiddenTagsPopup`
- **Text input** — flex-grows into remaining space
- **Clear all button** — pinned right, appears when input or tags have values
- **Off-screen measurement divs** — used by `useAutoLimitTags` to compute available width

## Usage Example

```typescript
import { TagSearchInput, TagSearchOption } from "./tag-search-input"

const options: TagSearchOption<number>[] = [
  { label: "Windows", value: 1 },
  { label: "macOS", value: 2 },
  { label: "Linux", value: 3 },
]

function FilterBar() {
  const [tags, setTags] = useState(options)
  const [search, setSearch] = useState("")

  return (
    <TagSearchInput<number>
      tags={tags}
      searchValue={search}
      onSearchChange={setSearch}
      onTagRemove={(val) => setTags((prev) => prev.filter((t) => t.value !== val))}
      onClearAll={() => { setTags([]); setSearch("") }}
      onSubmit={(val) => console.log("submitted:", val)}
      limitTags="auto"
      placeholder="Filter devices..."
    />
  )
}
```