npm package: @quickcreator/quick-search
Description: A modern, embeddable search component built with React and Tailwind CSS. Features Shadow DOM isolation, infinite scroll, keyboard navigation, and i18n support.
Author: QuickCreator
Latest version: 1.0.2

# @quickcreator/quick-search

A modern, embeddable search component built with React and Tailwind CSS. Features Shadow DOM style isolation, infinite scrolling, keyboard navigation, and multi-language support.

[![npm version](https://img.shields.io/npm/v/@quickcreator/quick-search.svg)](https://www.npmjs.com/package/@quickcreator/quick-search)
[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)

## ✨ Features

- 🎨 **Style Isolation** - Uses Shadow DOM, won't affect page styles
- 🔍 **Dual Search Modes** - Supports server-side search and client-side filtering
- ♾️ **Infinite Scroll** - Automatic pagination with load-more functionality
- ⌨️ **Keyboard Navigation** - Supports Cmd/Ctrl+K, arrow keys, Enter, ESC
- 🌍 **Internationalization** - Built-in English and Chinese, custom language support
- 🎯 **TypeScript** - Full type definitions
- 📱 **Responsive** - Mobile-friendly design
- 🎭 **Theme Adaptive** - Automatically inherits page CSS variables

## 📦 Installation

### Via npm/yarn/pnpm

```bash
npm install @quickcreator/quick-search
# or
yarn add @quickcreator/quick-search
# or
pnpm add @quickcreator/quick-search
```

### Via CDN

```html
<!-- CSS -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@quickcreator/quick-search/dist/quickcreator-search-react.css">

<!-- JavaScript -->
<script src="https://cdn.jsdelivr.net/npm/@quickcreator/quick-search/dist/quickcreator-search-react.js"></script>
```

## 🚀 Quick Start

### Basic Usage (CDN)

```html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>Search Example</title>
  
  <!-- 1. Include CSS -->
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@quickcreator/quick-search/dist/quickcreator-search-react.css">
  
  <!-- 2. Define CSS Variables (optional, for theme adaptation) -->
  <style>
    :root {
      --background-color: #ffffff;
      --heading-color: #0f172a;
      --body-color: #334155;
      --muted-bg-color: #f1f5f9;
      --primary-accent-color: #6366f1;
    }
  </style>
</head>
<body>
  <!-- 3. Add search button -->
  <button data-quickcreator-search>Search</button>
  
  <!-- 4. Configure search options -->
  <script>
    window.QuickCreatorSearchConfig = {
      // Server-side search API endpoint
      fetchUrl: '/api/search-index',
      // Or use custom data loading function
      // fetchPosts: async () => { ... },
    };
  </script>
  
  <!-- 5. Include JS -->
  <script src="https://cdn.jsdelivr.net/npm/@quickcreator/quick-search/dist/quickcreator-search-react.js"></script>
</body>
</html>
```

## ⚙️ Configuration Options

Configure the component via `window.QuickCreatorSearchConfig`:

```javascript
window.QuickCreatorSearchConfig = {
  // ===== Search Mode Configuration =====
  
  // Option 1: Server-side search (recommended)
  fetchUrl: '/api/search-index',  // Search API endpoint
  
  // Option 2: Custom search function
  // fetchPosts: async () => {
  //   const response = await fetch('/api/posts');
  //   return await response.json();
  // },
  
  // ===== General Configuration =====
  
  pageSize: 10,              // Results per page (default: 5)
  debounceDelay: 300,        // Debounce delay in milliseconds (default: 300)
  minQueryLength: 2,         // Minimum query length (default: 2)
  
  // ===== Style Configuration =====
  
  cssUrl: '/path/to/custom.css',  // Custom CSS file path
  cssMode: 'auto',                // CSS injection mode: 'auto' | 'link' | 'adopted' | 'inline'
  containerId: 'my-search-host',  // Shadow DOM container ID
  
  // ===== Other Configuration =====
  
  baseUrl: 'https://example.com', // Base URL for resolving relative paths
  
  // Custom language text
  locale: {
    placeholder: 'Search articles...',
    empty: 'Type to start searching',
    loading: 'Loading...',
    noResults: 'No results found',
    close: 'Close',
    loadMore: 'Scroll to load more...',
    allLoaded: 'All results loaded'
  }
};
```

## 🔌 Two Search Modes

### Mode 1: Server-side Search (Recommended)

Suitable for large datasets, supports pagination and infinite scrolling.

**API Requirements:**

```typescript
// Request format
GET /api/search-index?q=keyword&page=1&limit=10

// Response format
{
  "posts": [
    {
      "title": "Article Title",
      "url": "/post/example",
      "excerpt": "Article excerpt",
      "feature_image": "/images/cover.jpg",
      "tags": [{ "name": "Tag" }],
      "author": { "name": "Author" },
      "published_at": "2024-01-01T00:00:00Z"
    }
  ],
  "meta": {
    "pagination": {
      "page": 1,
      "limit": 10,
      "total": 100,
      "pages": 10,
      "prev": null,
      "next": 2
    }
  }
}
```

**Configuration Example:**

```javascript
window.QuickCreatorSearchConfig = {
  fetchUrl: '/api/search-index',
  pageSize: 10
};
```

### Mode 2: Client-side Filtering

Suitable for small datasets, loads all articles at once for local filtering.

**Configuration Example:**

```javascript
window.QuickCreatorSearchConfig = {
  fetchPosts: async () => {
    const response = await fetch('/api/posts');
    const data = await response.json();
    return data.posts; // Return posts array
  }
};
```

If no configuration is provided, the component will automatically extract article information from the page (by finding `<article>` tags).

## 🎨 Theme Customization

The component uses CSS variables for theme adaptation. Simply define these variables on your page:

```css
:root {
  --background-color: #ffffff;      /* Background color */
  --heading-color: #0f172a;         /* Heading color */
  --body-color: #334155;            /* Text color */
  --muted-bg-color: #f1f5f9;        /* Secondary background color */
  --primary-accent-color: #6366f1;  /* Accent color */
}

/* Dark mode */
.dark {
  --background-color: #0b1220;
  --heading-color: #e5e7eb;
  --body-color: #94a3b8;
  --muted-bg-color: #111827;
  --primary-accent-color: #818cf8;
}
```

## ⌨️ Keyboard Shortcuts

- `Cmd/Ctrl + K` - Open search
- `↑ / ↓` - Navigate results
- `Enter` - Open selected result
- `ESC` - Close search

## 🌍 Multi-language Support

Built-in languages: `en` (English), `zh`/`zh-CN` (Simplified Chinese), `zh-TW` (Traditional Chinese)

**Automatic Language Detection:**

```javascript
// 1. From data-locale attribute
window.QuickCreatorSearchConfig = {
  'data-locale': 'en'
};

// 2. From HTML lang attribute
<html lang="en">

// 3. Custom language text
window.QuickCreatorSearchConfig = {
  locale: {
    placeholder: 'Search...',
    loading: 'Loading...',
    noResults: 'No results found',
    // ...
  }
};
```

## 🔧 API Methods

The component exposes global methods for programmatic control:

```javascript
// Open search
window.QuickCreatorSearchOpen();

// Close search
window.QuickCreatorSearchClose();

// Manual mount (if needed)
window.QuickCreatorSearch.mount({
  fetchUrl: '/api/search',
  // ...other config
});
```

## 📝 TypeScript Support

```typescript
import type { SearchPost, SearchApiResponse, LocaleStrings } from '@quickcreator/quick-search';

// Post type
const post: SearchPost = {
  title: 'Title',
  url: '/post/example',
  excerpt: 'Excerpt',
  feature_image: '/image.jpg',
  tags: [{ name: 'Tag' }],
  author: { name: 'Author' },
  published_at: '2024-01-01T00:00:00Z'
};

// API response type
const response: SearchApiResponse = {
  posts: [post],
  meta: {
    pagination: {
      page: 1,
      limit: 10,
      total: 100,
      pages: 10,
      prev: null,
      next: 2
    }
  }
};
```

## 🏗️ Build

```bash
# Install dependencies
npm install

# Development mode (auto rebuild)
npm run dev

# Production build
npm run build
```

## 📄 License

MIT © QuickCreator

## 🤝 Contributing

Issues and Pull Requests are welcome!

## 📮 Support

- Documentation: [GitHub](https://github.com/quickcreator/quickcreator-search-react)
- Bug Reports: [Issues](https://github.com/quickcreator/quickcreator-search-react/issues)