npm package: @magicx-eng/ai-autocomplete-react
Description: AI Autocomplete React SDK — guided autocomplete with pill-based input and dropdown suggestions
Latest version: 0.1.17

# @magicx/ai-autocomplete-react

A React/TypeScript SDK that provides a guided AI-powered autocomplete experience with pill-based input and dropdown suggestions.

## Features

- **Two tiers of integration** — use the full `<AIAutocomplete />` component or go headless with `useAIAutocomplete()` + `<AIAutocompleteDropdown />`
- **Pill-based input** — inline pills for unfilled parameters, bold text for completed ones
- **Keyboard navigation** — arrow keys, enter, tab, escape, backspace
- **Client-side filtering** — instant option filtering while typing
- **Accessible** — ARIA combobox pattern with `role="listbox"`, `aria-activedescendant`
- **Lightweight** — zero dependencies beyond React, < 15 kB gzipped
- **TypeScript first** — full type definitions shipped with the package

## Prerequisites

- [Node.js](https://nodejs.org/) >= 18
- [pnpm](https://pnpm.io/) >= 8

## Installation

```bash
pnpm add @magicx/ai-autocomplete-react
```

### Peer Dependencies

This library requires React 17 or later as a peer dependency:

```bash
pnpm add react react-dom
```

## Setup

### Authentication

Configure the API key via the `apiConfig` prop (recommended) or environment variable:

```tsx
// Option 1: Runtime config (recommended)
<AIAutocomplete
  apiConfig={{ apiKey: "your_api_key", authScheme: "Bearer" }}
  onSubmit={(result) => console.log(result)}
/>

// Option 2: Environment variable (build-time fallback)
// Add to your .env: MAGICX_AI_AUTOCOMPLETE_API_KEY=your_api_key_here
```

> **Note:** If using env vars and your framework requires prefixes (e.g. `NEXT_PUBLIC_`, `VITE_`), map them accordingly in your build config.

## Usage

### Tier 1: Full Component

Drop-in component that owns the input, pills, and dropdown:

```tsx
import { AIAutocomplete } from "@magicx/ai-autocomplete-react";

function App() {
  return (
    <AIAutocomplete
      onSubmit={(result) => console.log(result)}
      className="my-autocomplete"
    />
  );
}
```

### Tier 2: Headless

Use the hook and dropdown separately for full control over the input and pill rendering:

```tsx
import { useAIAutocomplete, AIAutocompleteDropdown } from "@magicx/ai-autocomplete-react";

function App() {
  const autocomplete = useAIAutocomplete({
    onSubmit: (result) => console.log(result),
  });

  return (
    <div>
      {autocomplete.completedParams.map((param) => (
        <strong key={param.id}>{param.text}</strong>
      ))}
      {autocomplete.suggestionPills.map((pill) => (
        <span key={pill.type}>{pill.text}</span>
      ))}
      <textarea {...autocomplete.inputProps} />
      <AIAutocompleteDropdown {...autocomplete.dropdownProps} />
    </div>
  );
}
```

## Development

### Getting Started

1. **Clone the repository:**

   ```bash
   git clone <repo-url>
   cd ai-autocomplete-react
   ```

2. **Install dependencies:**

   ```bash
   pnpm install
   ```

3. **Start the playground:**

   ```bash
   pnpm dev
   ```

   This launches a Vite dev server at `http://localhost:5173` with hot module replacement. Changes in `src/` are reflected instantly.

### Scripts

| Command | Description |
|---|---|
| `pnpm dev` | Start the playground (Vite dev server) |
| `pnpm build` | Build the library with tsup (ESM + CJS + `.d.ts`) |
| `pnpm lint` | Lint and format check with Biome |
| `pnpm lint:fix` | Auto-fix lint and format issues |
| `pnpm format` | Auto-format all files |
| `pnpm test` | Run tests with Vitest |
| `pnpm test:watch` | Run tests in watch mode |
| `pnpm test:coverage` | Run tests with coverage report |
| `pnpm typecheck` | Type-check with TypeScript (no emit) |

### Project Structure

```
ai-autocomplete-react/
├── src/                          # Library source code
│   ├── index.ts                  # Public barrel — exports component + types
│   ├── hooks/                    # React hooks (core composition + sub-hooks)
│   ├── components/               # Internal UI components
│   └── utils/                    # Pure functions (API, query builder, filtering, segments)
├── playground/                   # Vite dev app for local testing (not published)
│   ├── index.html
│   ├── main.tsx
│   ├── App.tsx
│   └── vite.config.ts
├── tests/                        # Test files
├── tsup.config.ts                # Library bundler config
├── vitest.config.ts              # Test runner config
├── tsconfig.json                 # TypeScript config
├── biome.json                    # Linter + formatter config
└── package.json
```

### Playground

The `playground/` directory is a standalone Vite app for manually testing the component during development. It imports directly from `src/` via a path alias — no build step required.

To use the playground with a real server endpoint, create a `.env` file in the playground directory:

```bash
# playground/.env
MAGICX_AI_AUTOCOMPLETE_API_KEY=your_dev_api_key
```

The playground is **not published** with the library. Only the `dist/` folder ships to npm.

#### Running Different Demos

```bash
pnpm dev                          # ActiveCampaign (default)
VITE_DEMO=nubank pnpm dev         # Nubank
```

The demos use different `typewriterEffect` settings:
- **ActiveCampaign** (`typewriterEffect={false}`) — shimmer sweep on option select, no letter-by-letter reveal.
- **Nubank** (`typewriterEffect={true}`) — letter-by-letter typewriter reveal with shimmer.

### Deploying Demo Pages

Both demo apps are built from the same codebase, controlled by the `VITE_DEMO` env var.

#### ActiveCampaign

```bash
# 1. (Skip if first time) Remove previously built files
rm -rf playground/dist/*

# 2. Build
VITE_DEMO=activecampaign pnpm build:playground

# 3. Remove existing demo files
rm -rf $HERO_AUTOCOMPLETE_REPO/web/b2b/active-campaign/*

# 4. Copy build artifacts
cp -r playground/dist/* $HERO_AUTOCOMPLETE_REPO/web/b2b/active-campaign/

# 5. Commit the hero-autocomplete repo
```

#### Nubank

```bash
# 1. (Skip if first time) Remove previously built files
rm -rf playground/dist/*

# 2. Build
VITE_DEMO=nubank pnpm build:playground

# 3. Remove existing demo files (note: nubank uses a `textbox` subfolder)
rm -rf $HERO_AUTOCOMPLETE_REPO/web/b2b/nubank/textbox/*

# 4. Copy build artifacts
cp -r playground/dist/* $HERO_AUTOCOMPLETE_REPO/web/b2b/nubank/textbox/

# 5. Commit the hero-autocomplete repo
```

#### Notes

- **API endpoint**: `/api/suggest` is used automatically in local dev (the Vite proxy forwards to `localhost:8080`). Production builds use `/ac/api/suggest` automatically — the `/ac` prefix is required by the deployed reverse proxy.
- **Auth**: Controlled by `MAGICX_AUTH_SCHEME` in `.env`. Set to `Basic` for local dev (credentials are base64-encoded). Production builds omit the auth header when no API key is set (the reverse proxy handles authentication).

### Environment Variables

| Variable | Where | Purpose |
|---|---|---|
| `VITE_DEMO` | Build/dev | `activecampaign` (default) or `nubank` |
| `MAGICX_AI_AUTOCOMPLETE_API_KEY` | `.env` | Generic API key (takes priority over demo-specific keys) |
| `MAGICX_AI_AUTOCOMPLETE_API_KEY_ACTIVECAMPAIGN` | `.env` | ActiveCampaign credentials (`user:pass`) |
| `MAGICX_AI_AUTOCOMPLETE_API_KEY_NUBANK` | `.env` | Nubank credentials (`user:pass`) |
| `MAGICX_AUTH_SCHEME` | `.env` | Auth header scheme: `Basic` or `Bearer` (default) |
| `MAGICX_APP_IDENTIFIER` | Build | App identifier header (auto-set by `VITE_DEMO`) |

### Basic Example

A minimal Vite app at `examples/basic/` that consumes the library from npm. Use it to verify the published package works end-to-end after a release.

```bash
cd examples/basic
pnpm install   # installs @magicx-eng/ai-autocomplete-react from npm
pnpm dev       # starts on localhost:5174, proxies /api to localhost:8080
```

Update the version in `examples/basic/package.json` before testing a new release.

### Testing

Tests use [Vitest](https://vitest.dev/) with [React Testing Library](https://testing-library.com/docs/react-testing-library/intro/) and [MSW](https://mswjs.io/) for API mocking.

```bash
# Run all tests
pnpm test

# Watch mode
pnpm test:watch

# With coverage
pnpm test:coverage
```

### Building

```bash
pnpm build
```

This outputs to `dist/`:
- `index.js` — ESM build
- `index.cjs` — CommonJS build
- `index.d.ts` — TypeScript declarations

### Publishing to npm

Published as a private package under `@magicx-eng/ai-autocomplete-react`.

#### Setup (one-time)

1. Create a granular access token at https://www.npmjs.com/settings/magicx-eng/tokens
2. Add it to `.npmrc` in the project root:
   ```
   //registry.npmjs.org/:_authToken=YOUR_TOKEN_HERE
   ```
   (`.npmrc` is gitignored)

#### Publishing a new version

1. Bump the version in `package.json`
2. Build and publish:
   ```bash
   pnpm build && npm publish --access restricted
   ```
   This runs lint + test + build (via `prepublishOnly`), swaps in the npm-specific README, publishes, then restores the repo README.

3. To unpublish a version (within 72 hours):
   ```bash
   npm unpublish @magicx-eng/ai-autocomplete-react@X.Y.Z
   ```

#### npm README

The npm package page shows `npm-readme.md` (swapped in during publish via `prepack`/`postpack` scripts). Edit `npm-readme.md` for consumer-facing docs. The repo `README.md` is not published.

## Tech Stack

| Category | Choice |
|---|---|
| Language | TypeScript 5.x (strict) |
| Framework | React 17+ (peer dependency) |
| Bundler | tsup |
| Package Manager | pnpm |
| Testing | Vitest + React Testing Library + MSW |
| Linting | Biome |
| Styling | CSS Modules |